From 1ecd3902c6e16c2445165b872c49e73770b72da7 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Mon, 15 Oct 2007 23:05:07 -0600 Subject: [SCSI] fc4: remove this and all associated drivers This code has been slowly rotting for about eight years. It's currently impeding a few SCSI cleanups, and nobody seems to have hardware to test it any more. I talked to Dave Miller about it, and he agrees we can delete it. If anyone wants a software FC stack in future, they can retrieve this driver from git. Signed-off-by: Matthew Wilcox Acked-by: David S. Miller Signed-off-by: James Bottomley diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 59c4d75..5cc8847 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -456,8 +456,6 @@ source "drivers/Kconfig" source "drivers/sbus/char/Kconfig" -source "drivers/fc4/Kconfig" - source "fs/Kconfig" menu "Instrumentation Support" diff --git a/drivers/Makefile b/drivers/Makefile index 174c27e..8c645bc 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -34,7 +34,6 @@ obj-$(CONFIG_NUBUS) += nubus/ obj-$(CONFIG_ATM) += atm/ obj-y += macintosh/ obj-$(CONFIG_IDE) += ide/ -obj-$(CONFIG_FC4) += fc4/ obj-$(CONFIG_SCSI) += scsi/ obj-$(CONFIG_ATA) += ata/ obj-$(CONFIG_FUSION) += message/ diff --git a/drivers/fc4/Kconfig b/drivers/fc4/Kconfig deleted file mode 100644 index 345dbe6..0000000 --- a/drivers/fc4/Kconfig +++ /dev/null @@ -1,81 +0,0 @@ -# -# FC4 device configuration -# - -menu "Fibre Channel support" - -config FC4 - tristate "Fibre Channel and FC4 SCSI support" - ---help--- - Fibre Channel is a high speed serial protocol mainly used to - connect large storage devices to the computer; it is compatible with - and intended to replace SCSI. - - This is an experimental support for storage arrays connected to your - computer using optical fibre cables and the "X3.269-199X Fibre - Channel Protocol for SCSI" specification. If you want to use this, - you need to say Y here and to "SCSI support" as well as to the - drivers for the storage array itself and for the interface adapter - such as SOC or SOC+. This subsystem could even serve for IP - networking, with some code extensions. - - If unsure, say N. - -comment "FC4 drivers" - depends on FC4 - -config FC4_SOC - tristate "Sun SOC/Sbus" - depends on FC4!=n && SPARC - help - Serial Optical Channel is an interface card with one or two Fibre - Optic ports, each of which can be connected to a disk array. Note - that if you have older firmware in the card, you'll need the - microcode from the Solaris driver to make it work. - - To compile this support as a module, choose M here: the module will - be called soc. - -config FC4_SOCAL - tristate "Sun SOC+ (aka SOCAL)" - depends on FC4!=n && SPARC - ---help--- - Serial Optical Channel Plus is an interface card with up to two - Fibre Optic ports. This card supports FC Arbitrated Loop (usually - A5000 or internal FC disks in E[3-6]000 machines through the - Interface Board). You'll probably need the microcode from the - Solaris driver to make it work. - - To compile this support as a module, choose M here: the module will - be called socal. - -comment "FC4 targets" - depends on FC4 - -config SCSI_PLUTO - tristate "SparcSTORAGE Array 100 and 200 series" - depends on FC4!=n && SCSI - help - If you never bought a disk array made by Sun, go with N. - - To compile this support as a module, choose M here: the module will - be called pluto. - -config SCSI_FCAL - tristate "Sun Enterprise Network Array (A5000 and EX500)" if SPARC - depends on FC4!=n && SCSI - help - This driver drives FC-AL disks connected through a Fibre Channel - card using the drivers/fc4 layer (currently only SOCAL). The most - common is either A5000 array or internal disks in E[3-6]000 - machines. - - To compile this support as a module, choose M here: the module will - be called fcal. - -config SCSI_FCAL - prompt "Generic FC-AL disk driver" - depends on FC4!=n && SCSI && !SPARC - -endmenu - diff --git a/drivers/fc4/Makefile b/drivers/fc4/Makefile deleted file mode 100644 index 0db3fbb..0000000 --- a/drivers/fc4/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for the Linux Fibre Channel device drivers. -# - -fc4-objs := fc.o fc_syms.o - -obj-$(CONFIG_FC4) += fc4.o -obj-$(CONFIG_FC4_SOC) += soc.o -obj-$(CONFIG_FC4_SOCAL) += socal.o diff --git a/drivers/fc4/fc-al.h b/drivers/fc4/fc-al.h deleted file mode 100644 index 62d3ca4..0000000 --- a/drivers/fc4/fc-al.h +++ /dev/null @@ -1,27 +0,0 @@ -/* fc-al.h: Definitions for Fibre Channel Arbitrated Loop topology. - * - * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - * Sources: - * Fibre Channel Arbitrated Loop (FC-AL), ANSI, Rev. 4.5, 1995 - */ - -#ifndef __FC_AL_H -#define __FC_AL_H - -/* Loop initialization payloads */ -#define FC_AL_LISM 0x11010000 /* Select Master, 12B payload */ -#define FC_AL_LIFA 0x11020000 /* Fabric Assign AL_PA bitmap, 20B payload */ -#define FC_AL_LIPA 0x11030000 /* Previously Acquired AL_PA bitmap, 20B payload */ -#define FC_AL_LIHA 0x11040000 /* Hard Assigned AL_PA bitmap, 20B payload */ -#define FC_AL_LISA 0x11050000 /* Soft Assigned AL_PA bitmap, 20B payload */ -#define FC_AL_LIRP 0x11060000 /* Report AL_PA position map, 132B payload */ -#define FC_AL_LILP 0x11070000 /* Loop AL_PA position map, 132B payload */ - -typedef struct { - u32 magic; - u8 len; - u8 alpa[127]; -} fc_al_posmap; - -#endif /* !(__FC_H) */ diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c deleted file mode 100644 index 82de9e1..0000000 --- a/drivers/fc4/fc.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* fc.c: Generic Fibre Channel and FC4 SCSI driver. - * - * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz) - * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz) - * - * There are two kinds of Fibre Channel adapters used in Linux. Either - * the adapter is "smart" and does all FC bookkeeping by itself and - * just presents a standard SCSI interface to the operating system - * (that's e.g. the case with Qlogic FC cards), or leaves most of the FC - * bookkeeping to the OS (e.g. soc, socal). Drivers for the former adapters - * will look like normal SCSI drivers (with the exception of max_id will be - * usually 127), the latter on the other side allows SCSI, IP over FC and other - * protocols. This driver tree is for the latter adapters. - * - * This file should support both Point-to-Point and Arbitrated Loop topologies. - * - * Sources: - * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994 - * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995 - * Fibre Channel Arbitrated Loop (FC-AL), Rev. 4.5, 1995 - * Fibre Channel Private Loop SCSI Direct Attach (FC-PLDA), Rev. 2.1, 1997 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "fcp_impl.h" -#include - -/* #define FCDEBUG */ - -#define fc_printk printk ("%s: ", fc->name); printk - -#ifdef FCDEBUG -#define FCD(x) fc_printk x; -#define FCND(x) printk ("FC: "); printk x; -#else -#define FCD(x) -#define FCND(x) -#endif - -#ifdef __sparc__ -#define dma_alloc_consistent(d,s,p) sbus_alloc_consistent(d,s,p) -#define dma_free_consistent(d,s,v,h) sbus_free_consistent(d,s,v,h) -#define dma_map_single(d,v,s,dir) sbus_map_single(d,v,s,dir) -#define dma_unmap_single(d,h,s,dir) sbus_unmap_single(d,h,s,dir) -#define dma_map_sg(d,s,n,dir) sbus_map_sg(d,s,n,dir) -#define dma_unmap_sg(d,s,n,dir) sbus_unmap_sg(d,s,n,dir) -#else -#define dma_alloc_consistent(d,s,p) pci_alloc_consistent(d,s,p) -#define dma_free_consistent(d,s,v,h) pci_free_consistent(d,s,v,h) -#define dma_map_single(d,v,s,dir) pci_map_single(d,v,s,dir) -#define dma_unmap_single(d,h,s,dir) pci_unmap_single(d,h,s,dir) -#define dma_map_sg(d,s,n,dir) pci_map_sg(d,s,n,dir) -#define dma_unmap_sg(d,s,n,dir) pci_unmap_sg(d,s,n,dir) -#endif - -#define FCP_CMND(SCpnt) ((fcp_cmnd *)&(SCpnt->SCp)) -#define FC_SCMND(SCpnt) ((fc_channel *)(SCpnt->device->host->hostdata[0])) -#define SC_FCMND(fcmnd) ((struct scsi_cmnd *)((long)fcmnd - (long)&(((struct scsi_cmnd *)0)->SCp))) - -static int fcp_scsi_queue_it(fc_channel *, struct scsi_cmnd *, fcp_cmnd *, int); -void fcp_queue_empty(fc_channel *); - -static void fcp_scsi_insert_queue (fc_channel *fc, fcp_cmnd *fcmd) -{ - if (!fc->scsi_que) { - fc->scsi_que = fcmd; - fcmd->next = fcmd; - fcmd->prev = fcmd; - } else { - fc->scsi_que->prev->next = fcmd; - fcmd->prev = fc->scsi_que->prev; - fc->scsi_que->prev = fcmd; - fcmd->next = fc->scsi_que; - } -} - -static void fcp_scsi_remove_queue (fc_channel *fc, fcp_cmnd *fcmd) -{ - if (fcmd == fcmd->next) { - fc->scsi_que = NULL; - return; - } - if (fcmd == fc->scsi_que) - fc->scsi_que = fcmd->next; - fcmd->prev->next = fcmd->next; - fcmd->next->prev = fcmd->prev; -} - -fc_channel *fc_channels = NULL; - -#define LSMAGIC 620829043 -typedef struct { - /* Must be first */ - struct semaphore sem; - int magic; - int count; - logi *logi; - fcp_cmnd *fcmds; - atomic_t todo; - struct timer_list timer; - unsigned char grace[0]; -} ls; - -#define LSOMAGIC 654907799 -typedef struct { - /* Must be first */ - struct semaphore sem; - int magic; - int count; - fcp_cmnd *fcmds; - atomic_t todo; - struct timer_list timer; -} lso; - -#define LSEMAGIC 84482456 -typedef struct { - /* Must be first */ - struct semaphore sem; - int magic; - int status; - struct timer_list timer; -} lse; - -static void fcp_login_timeout(unsigned long data) -{ - ls *l = (ls *)data; - FCND(("Login timeout\n")) - up(&l->sem); -} - -static void fcp_login_done(fc_channel *fc, int i, int status) -{ - fcp_cmnd *fcmd; - logi *plogi; - fc_hdr *fch; - ls *l = (ls *)fc->ls; - - FCD(("Login done %d %d\n", i, status)) - if (i < l->count) { - if (fc->state == FC_STATE_FPORT_OK) { - FCD(("Additional FPORT_OK received with status %d\n", status)) - return; - } - switch (status) { - case FC_STATUS_OK: /* Oh, we found a fabric */ - case FC_STATUS_P_RJT: /* Oh, we haven't found any */ - fc->state = FC_STATE_FPORT_OK; - fcmd = l->fcmds + i; - plogi = l->logi + 3 * i; - dma_unmap_single (fc->dev, fcmd->cmd, 3 * sizeof(logi), - DMA_BIDIRECTIONAL); - plogi->code = LS_PLOGI; - memcpy (&plogi->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn)); - memcpy (&plogi->node_wwn, &fc->wwn_node, sizeof(fc_wwn)); - memcpy (&plogi->common, fc->common_svc, sizeof(common_svc_parm)); - memcpy (&plogi->class1, fc->class_svcs, 3*sizeof(svc_parm)); - fch = &fcmd->fch; - fcmd->token += l->count; - FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, fc->did); - FILL_FCHDR_SID(fch, fc->sid); -#ifdef FCDEBUG - { - int i; - unsigned *x = (unsigned *)plogi; - printk ("logi: "); - for (i = 0; i < 21; i++) - printk ("%08x ", x[i]); - printk ("\n"); - } -#endif - fcmd->cmd = dma_map_single (fc->dev, plogi, 3 * sizeof(logi), - DMA_BIDIRECTIONAL); - fcmd->rsp = fcmd->cmd + 2 * sizeof(logi); - if (fc->hw_enque (fc, fcmd)) - printk ("FC: Cannot enque PLOGI packet on %s\n", fc->name); - break; - case FC_STATUS_ERR_OFFLINE: - fc->state = FC_STATE_MAYBEOFFLINE; - FCD (("FC is offline %d\n", l->grace[i])) - break; - default: - printk ("FLOGI failed for %s with status %d\n", fc->name, status); - /* Do some sort of error recovery here */ - break; - } - } else { - i -= l->count; - if (fc->state != FC_STATE_FPORT_OK) { - FCD(("Unexpected N-PORT rsp received")) - return; - } - switch (status) { - case FC_STATUS_OK: - plogi = l->logi + 3 * i; - dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), - DMA_BIDIRECTIONAL); - if (!fc->wwn_dest.lo && !fc->wwn_dest.hi) { - memcpy (&fc->wwn_dest, &plogi[1].node_wwn, sizeof(fc_wwn)); - FCD(("Dest WWN %08x%08x\n", *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo)) - } else if (fc->wwn_dest.lo != plogi[1].node_wwn.lo || - fc->wwn_dest.hi != plogi[1].node_wwn.hi) { - printk ("%s: mismatch in wwns. Got %08x%08x, expected %08x%08x\n", - fc->name, - *(u32 *)&plogi[1].node_wwn, plogi[1].node_wwn.lo, - *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo); - } - fc->state = FC_STATE_ONLINE; - printk ("%s: ONLINE\n", fc->name); - if (atomic_dec_and_test (&l->todo)) - up(&l->sem); - break; - case FC_STATUS_ERR_OFFLINE: - fc->state = FC_STATE_OFFLINE; - dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), - DMA_BIDIRECTIONAL); - printk ("%s: FC is offline\n", fc->name); - if (atomic_dec_and_test (&l->todo)) - up(&l->sem); - break; - default: - printk ("PLOGI failed for %s with status %d\n", fc->name, status); - /* Do some sort of error recovery here */ - break; - } - } -} - -static void fcp_report_map_done(fc_channel *fc, int i, int status) -{ - fcp_cmnd *fcmd; - fc_hdr *fch; - unsigned char j; - ls *l = (ls *)fc->ls; - fc_al_posmap *p; - - FCD(("Report map done %d %d\n", i, status)) - switch (status) { - case FC_STATUS_OK: /* Ok, let's have a fun on a loop */ - dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), - DMA_BIDIRECTIONAL); - p = (fc_al_posmap *)(l->logi + 3 * i); -#ifdef FCDEBUG - { - u32 *u = (u32 *)p; - FCD(("%08x\n", u[0])) - u ++; - FCD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) - } -#endif - if ((p->magic & 0xffff0000) != FC_AL_LILP || !p->len) { - printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic); - fc->state = FC_STATE_OFFLINE; - } else { - fc->posmap = kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL); - if (!fc->posmap) { - printk("FC: Not enough memory, offlining channel\n"); - fc->state = FC_STATE_OFFLINE; - } else { - int k; - /* FIXME: This is where SOCAL transfers our AL-PA. - Keep it here till we found out what other cards do... */ - fc->sid = (p->magic & 0xff); - for (i = 0; i < p->len; i++) - if (p->alpa[i] == fc->sid) - break; - k = p->len; - if (i == p->len) - i = 0; - else { - p->len--; - i++; - } - fc->posmap->len = p->len; - for (j = 0; j < p->len; j++) { - if (i == k) i = 0; - fc->posmap->list[j] = p->alpa[i++]; - } - fc->state = FC_STATE_ONLINE; - } - } - printk ("%s: ONLINE\n", fc->name); - if (atomic_dec_and_test (&l->todo)) - up(&l->sem); - break; - case FC_STATUS_POINTTOPOINT: /* We're Point-to-Point, no AL... */ - FCD(("SID %d DID %d\n", fc->sid, fc->did)) - fcmd = l->fcmds + i; - dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi), - DMA_BIDIRECTIONAL); - fch = &fcmd->fch; - memset(l->logi + 3 * i, 0, 3 * sizeof(logi)); - FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT); - FILL_FCHDR_SID(fch, 0); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); - fch->param = 0; - l->logi [3 * i].code = LS_FLOGI; - fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi), - DMA_BIDIRECTIONAL); - fcmd->rsp = fcmd->cmd + sizeof(logi); - fcmd->cmdlen = sizeof(logi); - fcmd->rsplen = sizeof(logi); - fcmd->data = (dma_addr_t)NULL; - fcmd->class = FC_CLASS_SIMPLE; - fcmd->proto = TYPE_EXTENDED_LS; - if (fc->hw_enque (fc, fcmd)) - printk ("FC: Cannot enque FLOGI packet on %s\n", fc->name); - break; - case FC_STATUS_ERR_OFFLINE: - fc->state = FC_STATE_MAYBEOFFLINE; - FCD (("FC is offline %d\n", l->grace[i])) - break; - default: - printk ("FLOGI failed for %s with status %d\n", fc->name, status); - /* Do some sort of error recovery here */ - break; - } -} - -void fcp_register(fc_channel *fc, u8 type, int unregister) -{ - int size, i; - int slots = (fc->can_queue * 3) >> 1; - - FCND(("Going to %sregister\n", unregister ? "un" : "")) - - if (type == TYPE_SCSI_FCP) { - if (!unregister) { - fc->scsi_cmd_pool = (fcp_cmd *) - dma_alloc_consistent (fc->dev, - slots * (sizeof (fcp_cmd) + fc->rsp_size), - &fc->dma_scsi_cmd); - fc->scsi_rsp_pool = (char *)(fc->scsi_cmd_pool + slots); - fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd); - fc->scsi_bitmap_end = (slots + 63) & ~63; - size = fc->scsi_bitmap_end / 8; - fc->scsi_bitmap = kzalloc (size, GFP_KERNEL); - set_bit (0, fc->scsi_bitmap); - for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++) - set_bit (i, fc->scsi_bitmap); - fc->scsi_free = fc->can_queue; - fc->cmd_slots = kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL); - fc->abort_count = 0; - } else { - fc->scsi_name[0] = 0; - kfree (fc->scsi_bitmap); - kfree (fc->cmd_slots); - FCND(("Unregistering\n")); -#if 0 - if (fc->rst_pkt) { - if (fc->rst_pkt->eh_state == SCSI_STATE_UNUSED) - kfree(fc->rst_pkt); - else { - /* Can't happen. Some memory would be lost. */ - printk("FC: Reset in progress. Now?!"); - } - } -#endif - FCND(("Unregistered\n")); - } - } else - printk ("FC: %segistering unknown type %02x\n", unregister ? "Unr" : "R", type); -} - -static void fcp_scsi_done(struct scsi_cmnd *SCpnt); - -static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hdr *fch) -{ - fcp_cmnd *fcmd; - fcp_rsp *rsp; - int host_status; - struct scsi_cmnd *SCpnt; - int sense_len; - int rsp_status; - - fcmd = fc->cmd_slots[token]; - if (!fcmd) return; - rsp = (fcp_rsp *) (fc->scsi_rsp_pool + fc->rsp_size * token); - SCpnt = SC_FCMND(fcmd); - - if (SCpnt->done != fcp_scsi_done) - return; - - rsp_status = rsp->fcp_status; - FCD(("rsp_status %08x status %08x\n", rsp_status, status)) - switch (status) { - case FC_STATUS_OK: - host_status=DID_OK; - - if (rsp_status & FCP_STATUS_RESID) { -#ifdef FCDEBUG - FCD(("Resid %d\n", rsp->fcp_resid)) - { - fcp_cmd *cmd = fc->scsi_cmd_pool + token; - int i; - - printk ("Command "); - for (i = 0; i < sizeof(fcp_cmd); i+=4) - printk ("%08x ", *(u32 *)(((char *)cmd)+i)); - printk ("\nResponse "); - for (i = 0; i < fc->rsp_size; i+=4) - printk ("%08x ", *(u32 *)(((char *)rsp)+i)); - printk ("\n"); - } -#endif - } - - if (rsp_status & FCP_STATUS_SENSE_LEN) { - sense_len = rsp->fcp_sense_len; - if (sense_len > sizeof(SCpnt->sense_buffer)) sense_len = sizeof(SCpnt->sense_buffer); - memcpy(SCpnt->sense_buffer, ((char *)(rsp+1)), sense_len); - } - - if (fcmd->data) - dma_unmap_sg(fc->dev, scsi_sglist(SCpnt), - scsi_sg_count(SCpnt), - SCpnt->sc_data_direction); - break; - default: - host_status=DID_ERROR; /* FIXME */ - FCD(("Wrong FC status %d for token %d\n", status, token)) - break; - } - - if (status_byte(rsp_status) == QUEUE_FULL) { - printk ("%s: (%d,%d) Received rsp_status 0x%x\n", fc->name, SCpnt->device->channel, SCpnt->device->id, rsp_status); - } - - SCpnt->result = (host_status << 16) | (rsp_status & 0xff); -#ifdef FCDEBUG - if (host_status || SCpnt->result || rsp_status) printk("FC: host_status %d, packet status %d\n", - host_status, SCpnt->result); -#endif - SCpnt->done = fcmd->done; - fcmd->done=NULL; - clear_bit(token, fc->scsi_bitmap); - fc->scsi_free++; - FCD(("Calling scsi_done with %08x\n", SCpnt->result)) - SCpnt->scsi_done(SCpnt); -} - -void fcp_receive_solicited(fc_channel *fc, int proto, int token, int status, fc_hdr *fch) -{ - int magic; - FCD(("receive_solicited %d %d %d\n", proto, token, status)) - switch (proto) { - case TYPE_SCSI_FCP: - fcp_scsi_receive(fc, token, status, fch); break; - case TYPE_EXTENDED_LS: - case PROTO_REPORT_AL_MAP: - magic = 0; - if (fc->ls) - magic = ((ls *)(fc->ls))->magic; - if (magic == LSMAGIC) { - ls *l = (ls *)fc->ls; - int i = (token >= l->count) ? token - l->count : token; - - /* Let's be sure */ - if ((unsigned)i < l->count && l->fcmds[i].fc == fc) { - if (proto == TYPE_EXTENDED_LS) - fcp_login_done(fc, token, status); - else - fcp_report_map_done(fc, token, status); - break; - } - } - FCD(("fc %p fc->ls %p fc->cmd_slots %p\n", fc, fc->ls, fc->cmd_slots)) - if (proto == TYPE_EXTENDED_LS && !fc->ls && fc->cmd_slots) { - fcp_cmnd *fcmd; - - fcmd = fc->cmd_slots[token]; - if (fcmd && fcmd->ls && ((ls *)(fcmd->ls))->magic == LSEMAGIC) { - lse *l = (lse *)fcmd->ls; - - l->status = status; - up (&l->sem); - } - } - break; - case PROTO_OFFLINE: - if (fc->ls && ((lso *)(fc->ls))->magic == LSOMAGIC) { - lso *l = (lso *)fc->ls; - - if ((unsigned)token < l->count && l->fcmds[token].fc == fc) { - /* Wow, OFFLINE response arrived :) */ - FCD(("OFFLINE Response arrived\n")) - fc->state = FC_STATE_OFFLINE; - if (atomic_dec_and_test (&l->todo)) - up(&l->sem); - } - } - break; - - default: - break; - } -} - -void fcp_state_change(fc_channel *fc, int state) -{ - FCD(("state_change %d %d\n", state, fc->state)) - if (state == FC_STATE_ONLINE && fc->state == FC_STATE_MAYBEOFFLINE) - fc->state = FC_STATE_UNINITED; - else if (state == FC_STATE_ONLINE) - printk (KERN_WARNING "%s: state change to ONLINE\n", fc->name); - else - printk (KERN_ERR "%s: state change to OFFLINE\n", fc->name); -} - -int fcp_initialize(fc_channel *fcchain, int count) -{ - fc_channel *fc; - fcp_cmnd *fcmd; - int i, retry, ret; - ls *l; - - FCND(("fcp_inititialize %08lx\n", (long)fcp_init)) - FCND(("fc_channels %08lx\n", (long)fc_channels)) - FCND((" SID %d DID %d\n", fcchain->sid, fcchain->did)) - l = kzalloc(sizeof (ls) + count, GFP_KERNEL); - if (!l) { - printk ("FC: Cannot allocate memory for initialization\n"); - return -ENOMEM; - } - l->magic = LSMAGIC; - l->count = count; - FCND(("FCP Init for %d channels\n", count)) - init_MUTEX_LOCKED(&l->sem); - init_timer(&l->timer); - l->timer.function = fcp_login_timeout; - l->timer.data = (unsigned long)l; - atomic_set (&l->todo, count); - l->logi = kzalloc (count * 3 * sizeof(logi), GFP_KERNEL); - l->fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); - if (!l->logi || !l->fcmds) { - kfree (l->logi); - kfree (l->fcmds); - kfree (l); - printk ("FC: Cannot allocate DMA memory for initialization\n"); - return -ENOMEM; - } - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) { - fc->state = FC_STATE_UNINITED; - fc->rst_pkt = NULL; /* kmalloc when first used */ - } - /* First try if we are in a AL topology */ - FCND(("Initializing REPORT_MAP packets\n")) - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) { - fcmd = l->fcmds + i; - fc->login = fcmd; - fc->ls = (void *)l; - /* Assumes sizeof(fc_al_posmap) < 3 * sizeof(logi), which is true */ - fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi), - DMA_BIDIRECTIONAL); - fcmd->proto = PROTO_REPORT_AL_MAP; - fcmd->token = i; - fcmd->fc = fc; - } - for (retry = 0; retry < 8; retry++) { - int nqueued = 0; - FCND(("Sending REPORT_MAP/FLOGI/PLOGI packets\n")) - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) { - if (fc->state == FC_STATE_ONLINE || fc->state == FC_STATE_OFFLINE) - continue; - disable_irq(fc->irq); - if (fc->state == FC_STATE_MAYBEOFFLINE) { - if (!l->grace[i]) { - l->grace[i]++; - FCD(("Grace\n")) - } else { - fc->state = FC_STATE_OFFLINE; - enable_irq(fc->irq); - dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL); - if (atomic_dec_and_test (&l->todo)) - goto all_done; - } - } - ret = fc->hw_enque (fc, fc->login); - enable_irq(fc->irq); - if (!ret) { - nqueued++; - continue; - } - if (ret == -ENOSYS && fc->login->proto == PROTO_REPORT_AL_MAP) { - /* Oh yes, this card handles Point-to-Point only, so let's try that. */ - fc_hdr *fch; - - FCD(("SID %d DID %d\n", fc->sid, fc->did)) - fcmd = l->fcmds + i; - dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL); - fch = &fcmd->fch; - FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT); - FILL_FCHDR_SID(fch, 0); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); - fch->param = 0; - l->logi [3 * i].code = LS_FLOGI; - fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi), DMA_BIDIRECTIONAL); - fcmd->rsp = fcmd->cmd + sizeof(logi); - fcmd->cmdlen = sizeof(logi); - fcmd->rsplen = sizeof(logi); - fcmd->data = (dma_addr_t)NULL; - fcmd->class = FC_CLASS_SIMPLE; - fcmd->proto = TYPE_EXTENDED_LS; - } else - printk ("FC: Cannot enque FLOGI/REPORT_MAP packet on %s\n", fc->name); - } - - if (nqueued) { - l->timer.expires = jiffies + 5 * HZ; - add_timer(&l->timer); - - down(&l->sem); - if (!atomic_read(&l->todo)) { - FCND(("All channels answered in time\n")) - break; /* All fc channels have answered us */ - } - } - } -all_done: - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) { - fc->ls = NULL; - switch (fc->state) { - case FC_STATE_ONLINE: break; - case FC_STATE_OFFLINE: break; - default: dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL); - break; - } - } - del_timer(&l->timer); - kfree (l->logi); - kfree (l->fcmds); - kfree (l); - return 0; -} - -int fcp_forceoffline(fc_channel *fcchain, int count) -{ - fc_channel *fc; - fcp_cmnd *fcmd; - int i, ret; - lso l; - - memset (&l, 0, sizeof(lso)); - l.count = count; - l.magic = LSOMAGIC; - FCND(("FCP Force Offline for %d channels\n", count)) - init_MUTEX_LOCKED(&l.sem); - init_timer(&l.timer); - l.timer.function = fcp_login_timeout; - l.timer.data = (unsigned long)&l; - atomic_set (&l.todo, count); - l.fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL); - if (!l.fcmds) { - printk ("FC: Cannot allocate memory for forcing offline\n"); - return -ENOMEM; - } - FCND(("Initializing OFFLINE packets\n")) - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) { - fc->state = FC_STATE_UNINITED; - fcmd = l.fcmds + i; - fc->login = fcmd; - fc->ls = (void *)&l; - fcmd->did = fc->did; - fcmd->class = FC_CLASS_OFFLINE; - fcmd->proto = PROTO_OFFLINE; - fcmd->token = i; - fcmd->fc = fc; - disable_irq(fc->irq); - ret = fc->hw_enque (fc, fc->login); - enable_irq(fc->irq); - if (ret) printk ("FC: Cannot enque OFFLINE packet on %s\n", fc->name); - } - - l.timer.expires = jiffies + 5 * HZ; - add_timer(&l.timer); - down(&l.sem); - del_timer(&l.timer); - - for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) - fc->ls = NULL; - kfree (l.fcmds); - return 0; -} - -int fcp_init(fc_channel *fcchain) -{ - fc_channel *fc; - int count=0; - int ret; - - for (fc = fcchain; fc; fc = fc->next) { - fc->fcp_register = fcp_register; - count++; - } - - ret = fcp_initialize (fcchain, count); - if (ret) - return ret; - - if (!fc_channels) - fc_channels = fcchain; - else { - for (fc = fc_channels; fc->next; fc = fc->next); - fc->next = fcchain; - } - return ret; -} - -void fcp_release(fc_channel *fcchain, int count) /* count must > 0 */ -{ - fc_channel *fc; - fc_channel *fcx; - - for (fc = fcchain; --count && fc->next; fc = fc->next); - if (count) { - printk("FC: nothing to release\n"); - return; - } - - if (fc_channels == fcchain) - fc_channels = fc->next; - else { - for (fcx = fc_channels; fcx->next != fcchain; fcx = fcx->next); - fcx->next = fc->next; - } - fc->next = NULL; - - /* - * We've just grabbed fcchain out of the fc_channel list - * and zero-terminated it, while destroying the count. - * - * Freeing the fc's is the low level driver's responsibility. - */ -} - - -static void fcp_scsi_done(struct scsi_cmnd *SCpnt) -{ - if (FCP_CMND(SCpnt)->done) - FCP_CMND(SCpnt)->done(SCpnt); -} - -static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt, - fcp_cmnd *fcmd, int prepare) -{ - long i; - fcp_cmd *cmd; - u32 fcp_cntl; - if (prepare) { - i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end); - set_bit (i, fc->scsi_bitmap); - fcmd->token = i; - cmd = fc->scsi_cmd_pool + i; - - if (fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd)) { - /* Invalid channel/id/lun and couldn't map it into fcp_addr */ - clear_bit (i, fc->scsi_bitmap); - SCpnt->result = (DID_BAD_TARGET << 16); - SCpnt->scsi_done(SCpnt); - return 0; - } - fc->scsi_free--; - fc->cmd_slots[fcmd->token] = fcmd; - - if (SCpnt->device->tagged_supported) { - if (jiffies - fc->ages[SCpnt->device->channel * fc->targets + SCpnt->device->id] > (5 * 60 * HZ)) { - fc->ages[SCpnt->device->channel * fc->targets + SCpnt->device->id] = jiffies; - fcp_cntl = FCP_CNTL_QTYPE_ORDERED; - } else - fcp_cntl = FCP_CNTL_QTYPE_SIMPLE; - } else - fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED; - - if (!scsi_bufflen(SCpnt)) { - cmd->fcp_cntl = fcp_cntl; - fcmd->data = (dma_addr_t)NULL; - } else { - struct scatterlist *sg; - int nents; - - switch (SCpnt->cmnd[0]) { - case WRITE_6: - case WRITE_10: - case WRITE_12: - cmd->fcp_cntl = (FCP_CNTL_WRITE | fcp_cntl); break; - default: - cmd->fcp_cntl = (FCP_CNTL_READ | fcp_cntl); break; - } - - sg = scsi_sglist(SCpnt); - nents = dma_map_sg(fc->dev, sg, scsi_sg_count(SCpnt), - SCpnt->sc_data_direction); - fcmd->data = sg_dma_address(sg); - cmd->fcp_data_len = sg_dma_len(sg); - } - memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len); - memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len); - FCD(("XXX: %04x.%04x.%04x.%04x - %08x%08x%08x\n", cmd->fcp_addr[0], cmd->fcp_addr[1], cmd->fcp_addr[2], cmd->fcp_addr[3], *(u32 *)SCpnt->cmnd, *(u32 *)(SCpnt->cmnd+4), *(u32 *)(SCpnt->cmnd+8))) - } - FCD(("Trying to enque %p\n", fcmd)) - if (!fc->scsi_que) { - if (!fc->hw_enque (fc, fcmd)) { - FCD(("hw_enque succeeded for %p\n", fcmd)) - return 0; - } - } - FCD(("Putting into que1 %p\n", fcmd)) - fcp_scsi_insert_queue (fc, fcmd); - return 0; -} - -int fcp_scsi_queuecommand(struct scsi_cmnd *SCpnt, - void (* done)(struct scsi_cmnd *)) -{ - fcp_cmnd *fcmd = FCP_CMND(SCpnt); - fc_channel *fc = FC_SCMND(SCpnt); - - FCD(("Entering SCSI queuecommand %p\n", fcmd)) - if (SCpnt->done != fcp_scsi_done) { - fcmd->done = SCpnt->done; - SCpnt->done = fcp_scsi_done; - SCpnt->scsi_done = done; - fcmd->proto = TYPE_SCSI_FCP; - if (!fc->scsi_free) { - FCD(("FC: !scsi_free, putting cmd on ML queue\n")) -#if (FCP_SCSI_USE_NEW_EH_CODE == 0) - printk("fcp_scsi_queue_command: queue full, losing cmd, bad\n"); -#endif - return 1; - } - return fcp_scsi_queue_it(fc, SCpnt, fcmd, 1); - } - return fcp_scsi_queue_it(fc, SCpnt, fcmd, 0); -} - -void fcp_queue_empty(fc_channel *fc) -{ - fcp_cmnd *fcmd; - - FCD(("Queue empty\n")) - while ((fcmd = fc->scsi_que)) { - /* The hw told us we can try again queue some packet */ - if (fc->hw_enque (fc, fcmd)) - break; - fcp_scsi_remove_queue (fc, fcmd); - } -} - -int fcp_scsi_abort(struct scsi_cmnd *SCpnt) -{ - /* Internal bookkeeping only. Lose 1 cmd_slots slot. */ - fcp_cmnd *fcmd = FCP_CMND(SCpnt); - fc_channel *fc = FC_SCMND(SCpnt); - - /* - * We react to abort requests by simply forgetting - * about the command and pretending everything's sweet. - * This may or may not be silly. We can't, however, - * immediately reuse the command's cmd_slots slot, - * as its result may arrive later and we cannot - * check whether it is the aborted one, can't we? - * - * Therefore, after the first few aborts are done, - * we tell the scsi error handler to do something clever. - * It will eventually call host reset, refreshing - * cmd_slots for us. - * - * There is a theoretical chance that we sometimes allow - * more than can_queue packets to the jungle this way, - * but the worst outcome possible is a series of - * more aborts and eventually the dev_reset catharsis. - */ - - if (++fc->abort_count < (fc->can_queue >> 1)) { - SCpnt->result = DID_ABORT; - fcmd->done(SCpnt); - printk("FC: soft abort\n"); - return SUCCESS; - } else { - printk("FC: hard abort refused\n"); - return FAILED; - } -} - -#if 0 -void fcp_scsi_reset_done(struct scsi_cmnd *SCpnt) -{ - fc_channel *fc = FC_SCMND(SCpnt); - - fc->rst_pkt->eh_state = SCSI_STATE_FINISHED; - up(fc->rst_pkt->device->host->eh_action); -} -#endif - -#define FCP_RESET_TIMEOUT (2*HZ) - -int fcp_scsi_dev_reset(struct scsi_cmnd *SCpnt) -{ -#if 0 /* broken junk, but if davem wants to compile this driver, let him.. */ - unsigned long flags; - fcp_cmd *cmd; - fcp_cmnd *fcmd; - fc_channel *fc = FC_SCMND(SCpnt); - DECLARE_MUTEX_LOCKED(sem); - - if (!fc->rst_pkt) { - fc->rst_pkt = kmalloc(sizeof(SCpnt), GFP_KERNEL); - if (!fc->rst_pkt) return FAILED; - - fcmd = FCP_CMND(fc->rst_pkt); - - - fcmd->token = 0; - cmd = fc->scsi_cmd_pool + 0; - FCD(("Preparing rst packet\n")) - fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd); - fc->rst_pkt->device = SCpnt->device; - fc->rst_pkt->cmd_len = 0; - - fc->cmd_slots[0] = fcmd; - - cmd->fcp_cntl = FCP_CNTL_QTYPE_ORDERED | FCP_CNTL_RESET; - fcmd->data = (dma_addr_t)NULL; - fcmd->proto = TYPE_SCSI_FCP; - - memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len); - memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len); - FCD(("XXX: %04x.%04x.%04x.%04x - %08x%08x%08x\n", cmd->fcp_addr[0], cmd->fcp_addr[1], cmd->fcp_addr[2], cmd->fcp_addr[3], *(u32 *)SCpnt->cmnd, *(u32 *)(SCpnt->cmnd+4), *(u32 *)(SCpnt->cmnd+8))) - } else { - fcmd = FCP_CMND(fc->rst_pkt); - if (fc->rst_pkt->eh_state == SCSI_STATE_QUEUED) - return FAILED; /* or SUCCESS. Only these */ - } - fc->rst_pkt->done = NULL; - - - fc->rst_pkt->eh_state = SCSI_STATE_QUEUED; - init_timer(&fc->rst_pkt->eh_timeout); - fc->rst_pkt->eh_timeout.data = (unsigned long) fc->rst_pkt; - fc->rst_pkt->eh_timeout.expires = jiffies + FCP_RESET_TIMEOUT; - fc->rst_pkt->eh_timeout.function = (void (*)(unsigned long))fcp_scsi_reset_done; - - add_timer(&fc->rst_pkt->eh_timeout); - - /* - * Set up the semaphore so we wait for the command to complete. - */ - - fc->rst_pkt->device->host->eh_action = &sem; - - fc->rst_pkt->done = fcp_scsi_reset_done; - - spin_lock_irqsave(SCpnt->device->host->host_lock, flags); - fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0); - spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags); - - down(&sem); - - fc->rst_pkt->device->host->eh_action = NULL; - del_timer(&fc->rst_pkt->eh_timeout); - - /* - * See if timeout. If so, tell the host to forget about it. - * In other words, we don't want a callback any more. - */ - if (fc->rst_pkt->eh_state == SCSI_STATE_TIMEOUT ) { - fc->rst_pkt->eh_state = SCSI_STATE_UNUSED; - return FAILED; - } - fc->rst_pkt->eh_state = SCSI_STATE_UNUSED; -#endif - return SUCCESS; -} - -static int __fcp_scsi_host_reset(struct scsi_cmnd *SCpnt) -{ - fc_channel *fc = FC_SCMND(SCpnt); - fcp_cmnd *fcmd = FCP_CMND(SCpnt); - int i; - - printk ("FC: host reset\n"); - - for (i=0; i < fc->can_queue; i++) { - if (fc->cmd_slots[i] && SCpnt->result != DID_ABORT) { - SCpnt->result = DID_RESET; - fcmd->done(SCpnt); - fc->cmd_slots[i] = NULL; - } - } - fc->reset(fc); - fc->abort_count = 0; - if (fcp_initialize(fc, 1)) return SUCCESS; - else return FAILED; -} - -int fcp_scsi_host_reset(struct scsi_cmnd *SCpnt) -{ - unsigned long flags; - int rc; - - spin_lock_irqsave(SCpnt->device->host->host_lock, flags); - rc = __fcp_scsi_host_reset(SCpnt); - spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags); - - return rc; -} - -static int fcp_els_queue_it(fc_channel *fc, fcp_cmnd *fcmd) -{ - long i; - - i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end); - set_bit (i, fc->scsi_bitmap); - fcmd->token = i; - fc->scsi_free--; - fc->cmd_slots[fcmd->token] = fcmd; - return fcp_scsi_queue_it(fc, NULL, fcmd, 0); -} - -static int fc_do_els(fc_channel *fc, unsigned int alpa, void *data, int len) -{ - fcp_cmnd _fcmd, *fcmd; - fc_hdr *fch; - lse l; - int i; - - fcmd = &_fcmd; - memset(fcmd, 0, sizeof(fcp_cmnd)); - FCD(("PLOGI SID %d DID %d\n", fc->sid, alpa)) - fch = &fcmd->fch; - FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, alpa); - FILL_FCHDR_SID(fch, fc->sid); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); - fch->param = 0; - fcmd->cmd = dma_map_single (fc->dev, data, 2 * len, DMA_BIDIRECTIONAL); - fcmd->rsp = fcmd->cmd + len; - fcmd->cmdlen = len; - fcmd->rsplen = len; - fcmd->data = (dma_addr_t)NULL; - fcmd->fc = fc; - fcmd->class = FC_CLASS_SIMPLE; - fcmd->proto = TYPE_EXTENDED_LS; - - memset (&l, 0, sizeof(lse)); - l.magic = LSEMAGIC; - init_MUTEX_LOCKED(&l.sem); - l.timer.function = fcp_login_timeout; - l.timer.data = (unsigned long)&l; - l.status = FC_STATUS_TIMED_OUT; - fcmd->ls = (void *)&l; - - disable_irq(fc->irq); - fcp_els_queue_it(fc, fcmd); - enable_irq(fc->irq); - - for (i = 0;;) { - l.timer.expires = jiffies + 5 * HZ; - add_timer(&l.timer); - down(&l.sem); - del_timer(&l.timer); - if (l.status != FC_STATUS_TIMED_OUT) break; - if (++i == 3) break; - disable_irq(fc->irq); - fcp_scsi_queue_it(fc, NULL, fcmd, 0); - enable_irq(fc->irq); - } - - clear_bit(fcmd->token, fc->scsi_bitmap); - fc->scsi_free++; - dma_unmap_single (fc->dev, fcmd->cmd, 2 * len, DMA_BIDIRECTIONAL); - return l.status; -} - -int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport) -{ - logi *l; - int status; - - l = kzalloc(2 * sizeof(logi), GFP_KERNEL); - if (!l) return -ENOMEM; - l->code = LS_PLOGI; - memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn)); - memcpy (&l->node_wwn, &fc->wwn_node, sizeof(fc_wwn)); - memcpy (&l->common, fc->common_svc, sizeof(common_svc_parm)); - memcpy (&l->class1, fc->class_svcs, 3*sizeof(svc_parm)); - status = fc_do_els(fc, alpa, l, sizeof(logi)); - if (status == FC_STATUS_OK) { - if (l[1].code == LS_ACC) { -#ifdef FCDEBUG - u32 *u = (u32 *)&l[1].nport_wwn; - FCD(("AL-PA %02x: Port WWN %08x%08x Node WWN %08x%08x\n", alpa, - u[0], u[1], u[2], u[3])) -#endif - memcpy(nport, &l[1].nport_wwn, sizeof(fc_wwn)); - memcpy(node, &l[1].node_wwn, sizeof(fc_wwn)); - } else - status = FC_STATUS_BAD_RSP; - } - kfree(l); - return status; -} - -typedef struct { - unsigned int code; - unsigned params[4]; -} prli; - -int fc_do_prli(fc_channel *fc, unsigned char alpa) -{ - prli *p; - int status; - - p = kzalloc(2 * sizeof(prli), GFP_KERNEL); - if (!p) return -ENOMEM; - p->code = LS_PRLI; - p->params[0] = 0x08002000; - p->params[3] = 0x00000022; - status = fc_do_els(fc, alpa, p, sizeof(prli)); - if (status == FC_STATUS_OK && p[1].code != LS_PRLI_ACC && p[1].code != LS_ACC) - status = FC_STATUS_BAD_RSP; - kfree(p); - return status; -} - -MODULE_LICENSE("GPL"); - diff --git a/drivers/fc4/fc.h b/drivers/fc4/fc.h deleted file mode 100644 index 13f89d4..0000000 --- a/drivers/fc4/fc.h +++ /dev/null @@ -1,230 +0,0 @@ -/* fc.h: Definitions for Fibre Channel Physical and Signaling Interface. - * - * Copyright (C) 1996-1997,1999 Jakub Jelinek (jj@ultra.linux.cz) - * - * Sources: - * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994 - * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995 - */ - -#ifndef __FC_H -#define __FC_H - -/* World Wide Name */ -#define NAAID_IEEE 1 -#define NAAID_IEEE_EXT 2 -#define NAAID_LOCAL 3 -#define NAAID_IP 4 -#define NAAID_IEEE_REG 5 -#define NAAID_IEEE_REG_EXT 6 -#define NAAID_CCITT 12 -#define NAAID_CCITT_GRP 14 - -/* This is NAAID_IEEE_EXT scheme */ -typedef struct { - u32 naaid:4; - u32 nportid:12; - u32 hi:16; - u32 lo; -} fc_wwn; - -/* Frame header for FC-PH frames */ - -/* r_ctl field */ -#define R_CTL_DEVICE_DATA 0x00 /* FC4 Device_Data frame */ -#define R_CTL_EXTENDED_SVC 0x20 /* Extended Link_Data frame */ -#define R_CTL_FC4_SVC 0x30 /* FC4 Link_Data frame */ -#define R_CTL_VIDEO 0x40 /* Video_Data frame */ -#define R_CTL_BASIC_SVC 0x80 /* Basic Link_Data frame */ -#define R_CTL_LINK_CTL 0xc0 /* Link_Control frame */ -/* FC4 Device_Data frames */ -#define R_CTL_UNCATEGORIZED 0x00 -#define R_CTL_SOLICITED_DATA 0x01 -#define R_CTL_UNSOL_CONTROL 0x02 -#define R_CTL_SOLICITED_CONTROL 0x03 -#define R_CTL_UNSOL_DATA 0x04 -#define R_CTL_XFER_RDY 0x05 -#define R_CTL_COMMAND 0x06 -#define R_CTL_STATUS 0x07 -/* Basic Link_Data frames */ -#define R_CTL_LS_NOP 0x80 -#define R_CTL_LS_ABTS 0x81 -#define R_CTL_LS_RMC 0x82 -#define R_CTL_LS_BA_ACC 0x84 -#define R_CTL_LS_BA_RJT 0x85 -/* Extended Link_Data frames */ -#define R_CTL_ELS_REQ 0x22 -#define R_CTL_ELS_RSP 0x23 -/* Link_Control frames */ -#define R_CTL_ACK_1 0xc0 -#define R_CTL_ACK_N 0xc1 -#define R_CTL_P_RJT 0xc2 -#define R_CTL_F_RJT 0xc3 -#define R_CTL_P_BSY 0xc4 -#define R_CTL_F_BSY_DF 0xc5 -#define R_CTL_F_BSY_LC 0xc6 -#define R_CTL_LCR 0xc7 - -/* type field */ -#define TYPE_BASIC_LS 0x00 -#define TYPE_EXTENDED_LS 0x01 -#define TYPE_IS8802 0x04 -#define TYPE_IS8802_SNAP 0x05 -#define TYPE_SCSI_FCP 0x08 -#define TYPE_SCSI_GPP 0x09 -#define TYPE_HIPP_FP 0x0a -#define TYPE_IPI3_MASTER 0x11 -#define TYPE_IPI3_SLAVE 0x12 -#define TYPE_IPI3_PEER 0x13 - -/* f_ctl field */ -#define F_CTL_FILL_BYTES 0x000003 -#define F_CTL_XCHG_REASSEMBLE 0x000004 -#define F_CTL_RO_PRESENT 0x000008 -#define F_CTL_ABORT_SEQ 0x000030 -#define F_CTL_CONTINUE_SEQ 0x0000c0 -#define F_CTL_INVALIDATE_XID 0x004000 -#define F_CTL_XID_REASSIGNED 0x008000 -#define F_CTL_SEQ_INITIATIVE 0x010000 -#define F_CTL_CHAINED_SEQ 0x020000 -#define F_CTL_END_CONNECT 0x040000 -#define F_CTL_END_SEQ 0x080000 -#define F_CTL_LAST_SEQ 0x100000 -#define F_CTL_FIRST_SEQ 0x200000 -#define F_CTL_SEQ_CONTEXT 0x400000 -#define F_CTL_XCHG_CONTEXT 0x800000 - -typedef struct { - u32 r_ctl:8, did:24; - u32 xxx1:8, sid:24; - u32 type:8, f_ctl:24; - u32 seq_id:8, df_ctl:8, seq_cnt:16; - u16 ox_id, rx_id; - u32 param; -} fc_hdr; -/* The following are ugly macros to make setup of this structure faster */ -#define FILL_FCHDR_RCTL_DID(fch, r_ctl, did) *(u32 *)(fch) = ((r_ctl) << 24) | (did); -#define FILL_FCHDR_SID(fch, sid) *((u32 *)(fch)+1) = (sid); -#define FILL_FCHDR_TYPE_FCTL(fch, type, f_ctl) *((u32 *)(fch)+2) = ((type) << 24) | (f_ctl); -#define FILL_FCHDR_SEQ_DF_SEQ(fch, seq_id, df_ctl, seq_cnt) *((u32 *)(fch)+3) = ((seq_id) << 24) | ((df_ctl) << 16) | (seq_cnt); -#define FILL_FCHDR_OXRX(fch, ox_id, rx_id) *((u32 *)(fch)+4) = ((ox_id) << 16) | (rx_id); - -/* Well known addresses */ -#define FS_GENERAL_MULTICAST 0xfffff7 -#define FS_WELL_KNOWN_MULTICAST 0xfffff8 -#define FS_HUNT_GROUP 0xfffff9 -#define FS_MANAGEMENT_SERVER 0xfffffa -#define FS_TIME_SERVER 0xfffffb -#define FS_NAME_SERVER 0xfffffc -#define FS_FABRIC_CONTROLLER 0xfffffd -#define FS_FABRIC_F_PORT 0xfffffe -#define FS_BROADCAST 0xffffff - -/* Reject frames */ -/* The param field should be cast to this structure */ -typedef struct { - u8 action; - u8 reason; - u8 xxx; - u8 vendor_unique; -} rjt_param; - -/* Reject action codes */ -#define RJT_RETRY 0x01 -#define RJT_NONRETRY 0x02 - -/* Reject reason codes */ -#define RJT_INVALID_DID 0x01 -#define RJT_INVALID_SID 0x02 -#define RJT_NPORT_NOT_AVAIL_TEMP 0x03 -#define RJT_NPORT_NOT_AVAIL_PERM 0x04 -#define RJT_CLASS_NOT_SUPPORTED 0x05 -#define RJT_DELIMITER_ERROR 0x06 -#define RJT_TYPE_NOT_SUPPORTED 0x07 -#define RJT_INVALID_LINK_CONTROL 0x08 -#define RJT_INVALID_R_CTL 0x09 -#define RJT_INVALID_F_CTL 0x0a -#define RJT_INVALID_OX_ID 0x0b -#define RJT_INVALID_RX_ID 0x0c -#define RJT_INVALID_SEQ_ID 0x0d -#define RJT_INVALID_DF_CTL 0x0e -#define RJT_INVALID_SEQ_CNT 0x0f -#define RJT_INVALID_PARAMETER 0x10 -#define RJT_EXCHANGE_ERROR 0x11 -#define RJT_PROTOCOL_ERROR 0x12 -#define RJT_INCORRECT_LENGTH 0x13 -#define RJT_UNEXPECTED_ACK 0x14 -#define RJT_UNEXPECTED_LINK_RESP 0x15 -#define RJT_LOGIN_REQUIRED 0x16 -#define RJT_EXCESSIVE_SEQUENCES 0x17 -#define RJT_CANT_ESTABLISH_EXCHANGE 0x18 -#define RJT_SECURITY_NOT_SUPPORTED 0x19 -#define RJT_FABRIC_NA 0x1a -#define RJT_VENDOR_UNIQUE 0xff - - -#define SP_F_PORT_LOGIN 0x10 - -/* Extended SVC commands */ -#define LS_RJT 0x01000000 -#define LS_ACC 0x02000000 -#define LS_PRLI_ACC 0x02100014 -#define LS_PLOGI 0x03000000 -#define LS_FLOGI 0x04000000 -#define LS_LOGO 0x05000000 -#define LS_ABTX 0x06000000 -#define LS_RCS 0x07000000 -#define LS_RES 0x08000000 -#define LS_RSS 0x09000000 -#define LS_RSI 0x0a000000 -#define LS_ESTS 0x0b000000 -#define LS_ESTC 0x0c000000 -#define LS_ADVC 0x0d000000 -#define LS_RTV 0x0e000000 -#define LS_RLS 0x0f000000 -#define LS_ECHO 0x10000000 -#define LS_TEST 0x11000000 -#define LS_RRQ 0x12000000 -#define LS_IDENT 0x20000000 -#define LS_PRLI 0x20100014 -#define LS_DISPLAY 0x21000000 -#define LS_PRLO 0x21100014 -#define LS_PDISC 0x50000000 -#define LS_ADISC 0x52000000 - -typedef struct { - u8 fcph_hi, fcph_lo; - u16 buf2buf_credit; - u8 common_features; - u8 xxx1; - u16 buf2buf_size; - u8 xxx2; - u8 total_concurrent; - u16 off_by_info; - u32 e_d_tov; -} common_svc_parm; - -typedef struct { - u16 serv_opts; - u16 initiator_ctl; - u16 rcpt_ctl; - u16 recv_size; - u8 xxx1; - u8 concurrent_seqs; - u16 end2end_credit; - u16 open_seqs_per_xchg; - u16 xxx2; -} svc_parm; - -/* Login */ -typedef struct { - u32 code; - common_svc_parm common; - fc_wwn nport_wwn; - fc_wwn node_wwn; - svc_parm class1; - svc_parm class2; - svc_parm class3; -} logi; - -#endif /* !(__FC_H) */ diff --git a/drivers/fc4/fc_syms.c b/drivers/fc4/fc_syms.c deleted file mode 100644 index bd3918d..0000000 --- a/drivers/fc4/fc_syms.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * We should not even be trying to compile this if we are not doing - * a module. - */ -#include - -#ifdef CONFIG_MODULES - -#include -#include -#include - -#include "fcp_impl.h" - -EXPORT_SYMBOL(fcp_init); -EXPORT_SYMBOL(fcp_release); -EXPORT_SYMBOL(fcp_queue_empty); -EXPORT_SYMBOL(fcp_receive_solicited); -EXPORT_SYMBOL(fc_channels); -EXPORT_SYMBOL(fcp_state_change); -EXPORT_SYMBOL(fc_do_plogi); -EXPORT_SYMBOL(fc_do_prli); - -/* SCSI stuff */ -EXPORT_SYMBOL(fcp_scsi_queuecommand); -EXPORT_SYMBOL(fcp_scsi_abort); -EXPORT_SYMBOL(fcp_scsi_dev_reset); -EXPORT_SYMBOL(fcp_scsi_host_reset); - -#endif /* CONFIG_MODULES */ diff --git a/drivers/fc4/fcp.h b/drivers/fc4/fcp.h deleted file mode 100644 index 6aa34a7..0000000 --- a/drivers/fc4/fcp.h +++ /dev/null @@ -1,94 +0,0 @@ -/* fcp.h: Definitions for Fibre Channel Protocol. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - */ - -#ifndef __FCP_H -#define __FCP_H - -/* FCP addressing is hierarchical with up to 4 layers, MS first. - Exact meaning of the addresses is up to the vendor */ - -/* fcp_cntl field */ -#define FCP_CNTL_WRITE 0x00000001 /* Initiator write */ -#define FCP_CNTL_READ 0x00000002 /* Initiator read */ -#define FCP_CNTL_ABORT_TSK 0x00000200 /* Abort task set */ -#define FCP_CNTL_CLR_TASK 0x00000400 /* Clear task set */ -#define FCP_CNTL_RESET 0x00002000 /* Reset */ -#define FCP_CNTL_CLR_ACA 0x00004000 /* Clear ACA */ -#define FCP_CNTL_KILL_TASK 0x00008000 /* Terminate task */ -#define FCP_CNTL_QTYPE_MASK 0x00070000 /* Tagged queueing type */ -#define FCP_CNTL_QTYPE_SIMPLE 0x00000000 -#define FCP_CNTL_QTYPE_HEAD_OF_Q 0x00010000 -#define FCP_CNTL_QTYPE_ORDERED 0x00020000 -#define FCP_CNTL_QTYPE_ACA_Q_TAG 0x00040000 -#define FCP_CNTL_QTYPE_UNTAGGED 0x00050000 - -typedef struct { - u16 fcp_addr[4]; - u32 fcp_cntl; - u8 fcp_cdb[16]; - u32 fcp_data_len; -} fcp_cmd; - -/* fcp_status field */ -#define FCP_STATUS_MASK 0x000000ff /* scsi status of command */ -#define FCP_STATUS_RSP_LEN 0x00000100 /* response_len != 0 */ -#define FCP_STATUS_SENSE_LEN 0x00000200 /* sense_len != 0 */ -#define FCP_STATUS_RESID 0x00000400 /* resid != 0 */ - -typedef struct { - u32 xxx[2]; - u32 fcp_status; - u32 fcp_resid; - u32 fcp_sense_len; - u32 fcp_response_len; - /* u8 fcp_sense[fcp_sense_len]; */ - /* u8 fcp_response[fcp_response_len]; */ -} fcp_rsp; - -/* fcp errors */ - -/* rsp_info_type field */ -#define FCP_RSP_SCSI_BUS_ERR 0x01 -#define FCP_RSP_SCSI_PORT_ERR 0x02 -#define FCP_RSP_CARD_ERR 0x03 - -/* isp_status field */ -#define FCP_RSP_CMD_COMPLETE 0x0000 -#define FCP_RSP_CMD_INCOMPLETE 0x0001 -#define FCP_RSP_CMD_DMA_ERR 0x0002 -#define FCP_RSP_CMD_TRAN_ERR 0x0003 -#define FCP_RSP_CMD_RESET 0x0004 -#define FCP_RSP_CMD_ABORTED 0x0005 -#define FCP_RSP_CMD_TIMEOUT 0x0006 -#define FCP_RSP_CMD_OVERRUN 0x0007 - -/* isp_state_flags field */ -#define FCP_RSP_ST_GOT_BUS 0x0100 -#define FCP_RSP_ST_GOT_TARGET 0x0200 -#define FCP_RSP_ST_SENT_CMD 0x0400 -#define FCP_RSP_ST_XFRD_DATA 0x0800 -#define FCP_RSP_ST_GOT_STATUS 0x1000 -#define FCP_RSP_ST_GOT_SENSE 0x2000 - -/* isp_stat_flags field */ -#define FCP_RSP_STAT_DISC 0x0001 -#define FCP_RSP_STAT_SYNC 0x0002 -#define FCP_RSP_STAT_PERR 0x0004 -#define FCP_RSP_STAT_BUS_RESET 0x0008 -#define FCP_RSP_STAT_DEV_RESET 0x0010 -#define FCP_RSP_STAT_ABORTED 0x0020 -#define FCP_RSP_STAT_TIMEOUT 0x0040 -#define FCP_RSP_STAT_NEGOTIATE 0x0080 - -typedef struct { - u8 rsp_info_type; - u8 xxx; - u16 isp_status; - u16 isp_state_flags; - u16 isp_stat_flags; -} fcp_scsi_err; - -#endif /* !(__FCP_H) */ diff --git a/drivers/fc4/fcp_impl.h b/drivers/fc4/fcp_impl.h deleted file mode 100644 index 506338a..0000000 --- a/drivers/fc4/fcp_impl.h +++ /dev/null @@ -1,164 +0,0 @@ -/* fcp_impl.h: Generic SCSI on top of FC4 - our interface defines. - * - * Copyright (C) 1997-1999 Jakub Jelinek (jj@ultra.linux.cz) - * Copyright (C) 1998 Jirka Hanika (geo@ff.cuni.cz) - */ - -#ifndef _FCP_SCSI_H -#define _FCP_SCSI_H - -#include -#include "../scsi/scsi.h" - -#include "fc.h" -#include "fcp.h" -#include "fc-al.h" - -#include -#ifdef __sparc__ -#include -#endif - -/* 0 or 1 */ -#define FCP_SCSI_USE_NEW_EH_CODE 0 - -#define FC_CLASS_OUTBOUND 0x01 -#define FC_CLASS_INBOUND 0x02 -#define FC_CLASS_SIMPLE 0x03 -#define FC_CLASS_IO_WRITE 0x04 -#define FC_CLASS_IO_READ 0x05 -#define FC_CLASS_UNSOLICITED 0x06 -#define FC_CLASS_OFFLINE 0x08 - -#define PROTO_OFFLINE 0x02 -#define PROTO_REPORT_AL_MAP 0x03 -#define PROTO_FORCE_LIP 0x06 - -struct _fc_channel; - -typedef struct fcp_cmnd { - struct fcp_cmnd *next; - struct fcp_cmnd *prev; - void (*done)(struct scsi_cmnd *); - unsigned short proto; - unsigned short token; - unsigned int did; - /* FCP SCSI stuff */ - dma_addr_t data; - /* From now on this cannot be touched for proto == TYPE_SCSI_FCP */ - fc_hdr fch; - dma_addr_t cmd; - dma_addr_t rsp; - int cmdlen; - int rsplen; - int class; - int datalen; - /* This is just used as a verification during login */ - struct _fc_channel *fc; - void *ls; -} fcp_cmnd; - -typedef struct { - unsigned int len; - unsigned char list[0]; -} fcp_posmap; - -typedef struct _fc_channel { - struct _fc_channel *next; - int irq; - int state; - int sid; - int did; - char name[16]; - void (*fcp_register)(struct _fc_channel *, u8, int); - void (*reset)(struct _fc_channel *); - int (*hw_enque)(struct _fc_channel *, fcp_cmnd *); - fc_wwn wwn_node; - fc_wwn wwn_nport; - fc_wwn wwn_dest; - common_svc_parm *common_svc; - svc_parm *class_svcs; -#ifdef __sparc__ - struct sbus_dev *dev; -#else - struct pci_dev *dev; -#endif - struct module *module; - /* FCP SCSI stuff */ - short can_queue; - short abort_count; - int rsp_size; - fcp_cmd *scsi_cmd_pool; - char *scsi_rsp_pool; - dma_addr_t dma_scsi_cmd, dma_scsi_rsp; - unsigned long *scsi_bitmap; - long scsi_bitmap_end; - int scsi_free; - int (*encode_addr)(struct scsi_cmnd *, u16 *, struct _fc_channel *, fcp_cmnd *); - fcp_cmnd *scsi_que; - char scsi_name[4]; - fcp_cmnd **cmd_slots; - int channels; - int targets; - long *ages; - struct scsi_cmnd *rst_pkt; - fcp_posmap *posmap; - /* LOGIN stuff */ - fcp_cmnd *login; - void *ls; -} fc_channel; - -extern fc_channel *fc_channels; - -#define FC_STATE_UNINITED 0 -#define FC_STATE_ONLINE 1 -#define FC_STATE_OFFLINE 2 -#define FC_STATE_RESETING 3 -#define FC_STATE_FPORT_OK 4 -#define FC_STATE_MAYBEOFFLINE 5 - -#define FC_STATUS_OK 0 -#define FC_STATUS_P_RJT 2 -#define FC_STATUS_F_RJT 3 -#define FC_STATUS_P_BSY 4 -#define FC_STATUS_F_BSY 5 -#define FC_STATUS_ERR_OFFLINE 0x11 -#define FC_STATUS_TIMEOUT 0x12 -#define FC_STATUS_ERR_OVERRUN 0x13 -#define FC_STATUS_POINTTOPOINT 0x15 -#define FC_STATUS_AL 0x16 -#define FC_STATUS_UNKNOWN_CQ_TYPE 0x20 -#define FC_STATUS_BAD_SEG_CNT 0x21 -#define FC_STATUS_MAX_XCHG_EXCEEDED 0x22 -#define FC_STATUS_BAD_XID 0x23 -#define FC_STATUS_XCHG_BUSY 0x24 -#define FC_STATUS_BAD_POOL_ID 0x25 -#define FC_STATUS_INSUFFICIENT_CQES 0x26 -#define FC_STATUS_ALLOC_FAIL 0x27 -#define FC_STATUS_BAD_SID 0x28 -#define FC_STATUS_NO_SEQ_INIT 0x29 -#define FC_STATUS_TIMED_OUT -1 -#define FC_STATUS_BAD_RSP -2 - -void fcp_queue_empty(fc_channel *); -int fcp_init(fc_channel *); -void fcp_release(fc_channel *fc_chain, int count); -void fcp_receive_solicited(fc_channel *, int, int, int, fc_hdr *); -void fcp_state_change(fc_channel *, int); -int fc_do_plogi(fc_channel *, unsigned char, fc_wwn *, fc_wwn *); -int fc_do_prli(fc_channel *, unsigned char); - -#define for_each_fc_channel(fc) \ - for (fc = fc_channels; fc; fc = fc->next) - -#define for_each_online_fc_channel(fc) \ - for_each_fc_channel(fc) \ - if (fc->state == FC_STATE_ONLINE) - -int fcp_scsi_queuecommand(struct scsi_cmnd *, - void (* done) (struct scsi_cmnd *)); -int fcp_scsi_abort(struct scsi_cmnd *); -int fcp_scsi_dev_reset(struct scsi_cmnd *); -int fcp_scsi_host_reset(struct scsi_cmnd *); - -#endif /* !(_FCP_SCSI_H) */ diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c deleted file mode 100644 index d517734..0000000 --- a/drivers/fc4/soc.c +++ /dev/null @@ -1,764 +0,0 @@ -/* soc.c: Sparc SUNW,soc (Serial Optical Channel) Fibre Channel Sbus adapter support. - * - * Copyright (C) 1996,1997,1999 Jakub Jelinek (jj@ultra.linux.cz) - * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz) - * - * Sources: - * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994 - * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995 - * - * Supported hardware: - * Tested on SOC sbus card bought with SS1000 in Linux running on SS5 and Ultra1. - * For SOC sbus cards, you have to make sure your FCode is 1.52 or later. - * If you have older FCode, you should try to upgrade or get SOC microcode from Sun - * (the microcode is present in Solaris soc driver as well). In that case you need - * to #define HAVE_SOC_UCODE and format the microcode into soc_asm.c. For the exact - * format mail me and I will tell you. I cannot offer you the actual microcode though, - * unless Sun confirms they don't mind. - */ - -static char *version = - "soc.c:v1.3 9/Feb/99 Jakub Jelinek (jj@ultra.linux.cz), Jirka Hanika (geo@ff.cuni.cz)\n"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* #define SOCDEBUG */ -/* #define HAVE_SOC_UCODE */ - -#include "fcp_impl.h" -#include "soc.h" -#ifdef HAVE_SOC_UCODE -#include "soc_asm.h" -#endif - -#define soc_printk printk ("soc%d: ", s->soc_no); printk - -#ifdef SOCDEBUG -#define SOD(x) soc_printk x; -#else -#define SOD(x) -#endif - -#define for_each_soc(s) for (s = socs; s; s = s->next) -struct soc *socs = NULL; - -static inline void soc_disable(struct soc *s) -{ - sbus_writel(0, s->regs + IMASK); - sbus_writel(SOC_CMD_SOFT_RESET, s->regs + CMD); -} - -static inline void soc_enable(struct soc *s) -{ - SOD(("enable %08x\n", s->cfg)) - sbus_writel(0, s->regs + SAE); - sbus_writel(s->cfg, s->regs + CFG); - sbus_writel(SOC_CMD_RSP_QALL, s->regs + CMD); - SOC_SETIMASK(s, SOC_IMASK_RSP_QALL | SOC_IMASK_SAE); - SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMAK))); -} - -static void soc_reset(fc_channel *fc) -{ - soc_port *port = (soc_port *)fc; - struct soc *s = port->s; - - /* FIXME */ - soc_disable(s); - s->req[0].seqno = 1; - s->req[1].seqno = 1; - s->rsp[0].seqno = 1; - s->rsp[1].seqno = 1; - s->req[0].in = 0; - s->req[1].in = 0; - s->rsp[0].in = 0; - s->rsp[1].in = 0; - s->req[0].out = 0; - s->req[1].out = 0; - s->rsp[0].out = 0; - s->rsp[1].out = 0; - - /* FIXME */ - soc_enable(s); -} - -static inline void soc_solicited (struct soc *s) -{ - fc_hdr fchdr; - soc_rsp __iomem *hwrsp; - soc_cq_rsp *sw_cq; - int token; - int status; - fc_channel *fc; - - sw_cq = &s->rsp[SOC_SOLICITED_RSP_Q]; - - if (sw_cq->pool == NULL) - sw_cq->pool = (soc_req __iomem *) - (s->xram + xram_get_32low ((xram_p)&sw_cq->hw_cq->address)); - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); - SOD (("soc_solicited, %d pkts arrived\n", (sw_cq->in-sw_cq->out) & sw_cq->last)) - for (;;) { - hwrsp = (soc_rsp __iomem *)sw_cq->pool + sw_cq->out; - token = xram_get_32low ((xram_p)&hwrsp->shdr.token); - status = xram_get_32low ((xram_p)&hwrsp->status); - fc = (fc_channel *)(&s->port[(token >> 11) & 1]); - - if (status == SOC_OK) { - fcp_receive_solicited(fc, token >> 12, - token & ((1 << 11) - 1), - FC_STATUS_OK, NULL); - } else { - xram_copy_from(&fchdr, (xram_p)&hwrsp->fchdr, sizeof(fchdr)); - /* We have intentionally defined FC_STATUS_* constants - * to match SOC_* constants, otherwise we'd have to - * translate status. - */ - fcp_receive_solicited(fc, token >> 12, - token & ((1 << 11) - 1), - status, &fchdr); - } - - if (++sw_cq->out > sw_cq->last) { - sw_cq->seqno++; - sw_cq->out = 0; - } - - if (sw_cq->out == sw_cq->in) { - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); - if (sw_cq->out == sw_cq->in) { - /* Tell the hardware about it */ - sbus_writel((sw_cq->out << 24) | - (SOC_CMD_RSP_QALL & - ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q)), - s->regs + CMD); - - /* Read it, so that we're sure it has been updated */ - sbus_readl(s->regs + CMD); - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); - if (sw_cq->out == sw_cq->in) - break; - } - } - } -} - -static inline void soc_request (struct soc *s, u32 cmd) -{ - SOC_SETIMASK(s, s->imask & ~(cmd & SOC_CMD_REQ_QALL)); - SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK))); - - SOD(("Queues available %08x OUT %X %X\n", cmd, - xram_get_8((xram_p)&s->req[0].hw_cq->out), - xram_get_8((xram_p)&s->req[0].hw_cq->out))) - if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) { - fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port])); - if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out)) - fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); - } else { - fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); - } - if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE) - s->curr_port ^= 1; -} - -static inline void soc_unsolicited (struct soc *s) -{ - soc_rsp __iomem *hwrsp, *hwrspc; - soc_cq_rsp *sw_cq; - int count; - int status; - int flags; - fc_channel *fc; - - sw_cq = &s->rsp[SOC_UNSOLICITED_RSP_Q]; - if (sw_cq->pool == NULL) - sw_cq->pool = (soc_req __iomem *) - (s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address))); - - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); - SOD (("soc_unsolicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last)) - while (sw_cq->in != sw_cq->out) { - /* ...real work per entry here... */ - hwrsp = (soc_rsp __iomem *)sw_cq->pool + sw_cq->out; - - hwrspc = NULL; - flags = xram_get_16 ((xram_p)&hwrsp->shdr.flags); - count = xram_get_8 ((xram_p)&hwrsp->count); - fc = (fc_channel *)&s->port[flags & SOC_PORT_B]; - SOD(("FC %08lx fcp_state_change %08lx\n", - (long)fc, (long)fc->fcp_state_change)) - - if (count != 1) { - /* Ugh, continuation entries */ - u8 in; - - if (count != 2) { - printk("%s: Too many continuations entries %d\n", - fc->name, count); - goto update_out; - } - - in = sw_cq->in; - if (in < sw_cq->out) in += sw_cq->last + 1; - if (in < sw_cq->out + 2) { - /* Ask the hardware if they haven't arrived yet. */ - sbus_writel((sw_cq->out << 24) | - (SOC_CMD_RSP_QALL & - ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)), - s->regs + CMD); - - /* Read it, so that we're sure it has been updated */ - sbus_readl(s->regs + CMD); - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); - in = sw_cq->in; - if (in < sw_cq->out) - in += sw_cq->last + 1; - if (in < sw_cq->out + 2) /* Nothing came, let us wait */ - return; - } - if (sw_cq->out == sw_cq->last) - hwrspc = (soc_rsp __iomem *)sw_cq->pool; - else - hwrspc = hwrsp + 1; - } - - switch (flags & ~SOC_PORT_B) { - case SOC_STATUS: - status = xram_get_32low ((xram_p)&hwrsp->status); - switch (status) { - case SOC_ONLINE: - SOD(("State change to ONLINE\n")); - fcp_state_change(fc, FC_STATE_ONLINE); - break; - case SOC_OFFLINE: - SOD(("State change to OFFLINE\n")); - fcp_state_change(fc, FC_STATE_OFFLINE); - break; - default: - printk ("%s: Unknown STATUS no %d\n", - fc->name, status); - break; - } - break; - case (SOC_UNSOLICITED|SOC_FC_HDR): - { - int r_ctl = xram_get_8 ((xram_p)&hwrsp->fchdr); - unsigned len; - char buf[64]; - - if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) { - len = xram_get_32 ((xram_p)&hwrsp->shdr.bytecnt); - if (len < 4 || !hwrspc) { - printk ("%s: Invalid R_CTL %02x " - "continuation entries\n", - fc->name, r_ctl); - } else { - if (len > 60) - len = 60; - xram_copy_from (buf, (xram_p)hwrspc, - (len + 3) & ~3); - if (*(u32 *)buf == LS_DISPLAY) { - int i; - - for (i = 4; i < len; i++) - if (buf[i] == '\n') - buf[i] = ' '; - buf[len] = 0; - printk ("%s message: %s\n", - fc->name, buf + 4); - } else { - printk ("%s: Unknown LS_CMD " - "%02x\n", fc->name, - buf[0]); - } - } - } else { - printk ("%s: Unsolicited R_CTL %02x " - "not handled\n", fc->name, r_ctl); - } - } - break; - default: - printk ("%s: Unexpected flags %08x\n", fc->name, flags); - break; - }; -update_out: - if (++sw_cq->out > sw_cq->last) { - sw_cq->seqno++; - sw_cq->out = 0; - } - - if (hwrspc) { - if (++sw_cq->out > sw_cq->last) { - sw_cq->seqno++; - sw_cq->out = 0; - } - } - - if (sw_cq->out == sw_cq->in) { - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); - if (sw_cq->out == sw_cq->in) { - /* Tell the hardware about it */ - sbus_writel((sw_cq->out << 24) | - (SOC_CMD_RSP_QALL & - ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)), - s->regs + CMD); - - /* Read it, so that we're sure it has been updated */ - sbus_readl(s->regs + CMD); - sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in); - } - } - } -} - -static irqreturn_t soc_intr(int irq, void *dev_id) -{ - u32 cmd; - unsigned long flags; - register struct soc *s = (struct soc *)dev_id; - - spin_lock_irqsave(&s->lock, flags); - cmd = sbus_readl(s->regs + CMD); - for (; (cmd = SOC_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) { - if (cmd & SOC_CMD_RSP_Q1) soc_unsolicited (s); - if (cmd & SOC_CMD_RSP_Q0) soc_solicited (s); - if (cmd & SOC_CMD_REQ_QALL) soc_request (s, cmd); - } - spin_unlock_irqrestore(&s->lock, flags); - - return IRQ_HANDLED; -} - -#define TOKEN(proto, port, token) (((proto)<<12)|(token)|(port)) - -static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) -{ - soc_port *port = (soc_port *)fc; - struct soc *s = port->s; - int qno; - soc_cq_req *sw_cq; - int cq_next_in; - soc_req *request; - fc_hdr *fch; - int i; - - if (fcmd->proto == TYPE_SCSI_FCP) - qno = 1; - else - qno = 0; - SOD(("Putting a FCP packet type %d into hw queue %d\n", fcmd->proto, qno)) - if (s->imask & (SOC_IMASK_REQ_Q0 << qno)) { - SOD(("EIO %08x\n", s->imask)) - return -EIO; - } - sw_cq = s->req + qno; - cq_next_in = (sw_cq->in + 1) & sw_cq->last; - - if (cq_next_in == sw_cq->out && - cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) { - SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last)) - SOC_SETIMASK(s, s->imask | (SOC_IMASK_REQ_Q0 << qno)); - SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK))); - /* If queue is full, just say NO */ - return -EBUSY; - } - - request = sw_cq->pool + sw_cq->in; - fch = &request->fchdr; - - switch (fcmd->proto) { - case TYPE_SCSI_FCP: - request->shdr.token = TOKEN(TYPE_SCSI_FCP, port->mask, fcmd->token); - request->data[0].base = fc->dma_scsi_cmd + fcmd->token * sizeof(fcp_cmd); - request->data[0].count = sizeof(fcp_cmd); - request->data[1].base = fc->dma_scsi_rsp + fcmd->token * fc->rsp_size; - request->data[1].count = fc->rsp_size; - if (fcmd->data) { - request->shdr.segcnt = 3; - i = fc->scsi_cmd_pool[fcmd->token].fcp_data_len; - request->shdr.bytecnt = i; - request->data[2].base = fcmd->data; - request->data[2].count = i; - request->type = - (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ? - SOC_CQTYPE_IO_WRITE : SOC_CQTYPE_IO_READ; - } else { - request->shdr.segcnt = 2; - request->shdr.bytecnt = 0; - request->data[2].base = 0; - request->data[2].count = 0; - request->type = SOC_CQTYPE_SIMPLE; - } - FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did); - FILL_FCHDR_SID(fch, fc->sid); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, - F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); - fch->param = 0; - request->shdr.flags = port->flags; - request->shdr.class = 2; - break; - - case PROTO_OFFLINE: - memset (request, 0, sizeof(*request)); - request->shdr.token = TOKEN(PROTO_OFFLINE, port->mask, fcmd->token); - request->type = SOC_CQTYPE_OFFLINE; - FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did); - FILL_FCHDR_SID(fch, fc->sid); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, - F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); - request->shdr.flags = port->flags; - break; - - case PROTO_REPORT_AL_MAP: - /* SOC only supports Point-to-Point topology, no FC-AL, sorry... */ - return -ENOSYS; - - default: - request->shdr.token = TOKEN(fcmd->proto, port->mask, fcmd->token); - request->shdr.class = 2; - request->shdr.flags = port->flags; - memcpy (fch, &fcmd->fch, sizeof(fc_hdr)); - request->data[0].count = fcmd->cmdlen; - request->data[1].count = fcmd->rsplen; - request->type = fcmd->class; - switch (fcmd->class) { - case FC_CLASS_OUTBOUND: - request->data[0].base = fcmd->cmd; - request->data[0].count = fcmd->cmdlen; - request->type = SOC_CQTYPE_OUTBOUND; - request->shdr.bytecnt = fcmd->cmdlen; - request->shdr.segcnt = 1; - break; - case FC_CLASS_INBOUND: - request->data[0].base = fcmd->rsp; - request->data[0].count = fcmd->rsplen; - request->type = SOC_CQTYPE_INBOUND; - request->shdr.bytecnt = 0; - request->shdr.segcnt = 1; - break; - case FC_CLASS_SIMPLE: - request->data[0].base = fcmd->cmd; - request->data[1].base = fcmd->rsp; - request->data[0].count = fcmd->cmdlen; - request->data[1].count = fcmd->rsplen; - request->type = SOC_CQTYPE_SIMPLE; - request->shdr.bytecnt = fcmd->cmdlen; - request->shdr.segcnt = 2; - break; - case FC_CLASS_IO_READ: - case FC_CLASS_IO_WRITE: - request->data[0].base = fcmd->cmd; - request->data[1].base = fcmd->rsp; - request->data[0].count = fcmd->cmdlen; - request->data[1].count = fcmd->rsplen; - request->type = - (fcmd->class == FC_CLASS_IO_READ) ? - SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE; - if (fcmd->data) { - request->data[2].base = fcmd->data; - request->data[2].count = fcmd->datalen; - request->shdr.bytecnt = fcmd->datalen; - request->shdr.segcnt = 3; - } else { - request->shdr.bytecnt = 0; - request->shdr.segcnt = 2; - } - break; - }; - break; - }; - - request->count = 1; - request->flags = 0; - request->seqno = sw_cq->seqno; - - /* And now tell the SOC about it */ - - if (++sw_cq->in > sw_cq->last) { - sw_cq->in = 0; - sw_cq->seqno++; - } - - SOD(("Putting %08x into cmd\n", - SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno))) - - sbus_writel(SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno), - s->regs + CMD); - - /* Read so that command is completed. */ - sbus_readl(s->regs + CMD); - - return 0; -} - -static inline void soc_download_fw(struct soc *s) -{ -#ifdef HAVE_SOC_UCODE - xram_copy_to (s->xram, soc_ucode, sizeof(soc_ucode)); - xram_bzero (s->xram + sizeof(soc_ucode), 32768 - sizeof(soc_ucode)); -#endif -} - -/* Check for what the best SBUS burst we can use happens - * to be on this machine. - */ -static inline void soc_init_bursts(struct soc *s, struct sbus_dev *sdev) -{ - int bsizes, bsizes_more; - - bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff); - bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff); - bsizes &= bsizes_more; - if ((bsizes & 0x7f) == 0x7f) - s->cfg = SOC_CFG_BURST_64; - else if ((bsizes & 0x3f) == 0x3f) - s->cfg = SOC_CFG_BURST_32; - else if ((bsizes & 0x1f) == 0x1f) - s->cfg = SOC_CFG_BURST_16; - else - s->cfg = SOC_CFG_BURST_4; -} - -static inline void soc_init(struct sbus_dev *sdev, int no) -{ - unsigned char tmp[60]; - int propl; - struct soc *s; - static int version_printed = 0; - soc_hw_cq cq[8]; - int size, i; - int irq; - - s = kzalloc (sizeof (struct soc), GFP_KERNEL); - if (s == NULL) - return; - spin_lock_init(&s->lock); - s->soc_no = no; - - SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n", - (long)socs, (long)soc_intr, (long)soc_hw_enque)) - if (version_printed++ == 0) - printk (version); - - s->port[0].fc.module = THIS_MODULE; - s->port[1].fc.module = THIS_MODULE; - - s->next = socs; - socs = s; - s->port[0].fc.dev = sdev; - s->port[1].fc.dev = sdev; - s->port[0].s = s; - s->port[1].s = s; - - s->port[0].fc.next = &s->port[1].fc; - - /* World Wide Name of SOC */ - propl = prom_getproperty (sdev->prom_node, "soc-wwn", tmp, sizeof(tmp)); - if (propl != sizeof (fc_wwn)) { - s->wwn.naaid = NAAID_IEEE; - s->wwn.lo = 0x12345678; - } else - memcpy (&s->wwn, tmp, sizeof (fc_wwn)); - - propl = prom_getproperty (sdev->prom_node, "port-wwns", tmp, sizeof(tmp)); - if (propl != 2 * sizeof (fc_wwn)) { - s->port[0].fc.wwn_nport.naaid = NAAID_IEEE_EXT; - s->port[0].fc.wwn_nport.hi = s->wwn.hi; - s->port[0].fc.wwn_nport.lo = s->wwn.lo; - s->port[1].fc.wwn_nport.naaid = NAAID_IEEE_EXT; - s->port[1].fc.wwn_nport.nportid = 1; - s->port[1].fc.wwn_nport.hi = s->wwn.hi; - s->port[1].fc.wwn_nport.lo = s->wwn.lo; - } else { - memcpy (&s->port[0].fc.wwn_nport, tmp, sizeof (fc_wwn)); - memcpy (&s->port[1].fc.wwn_nport, tmp + sizeof (fc_wwn), sizeof (fc_wwn)); - } - memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); - memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); - SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n", - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, - *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) - - s->port[0].fc.sid = 1; - s->port[1].fc.sid = 17; - s->port[0].fc.did = 2; - s->port[1].fc.did = 18; - - s->port[0].fc.reset = soc_reset; - s->port[1].fc.reset = soc_reset; - - if (sdev->num_registers == 1) { - /* Probably SunFire onboard SOC */ - s->xram = sbus_ioremap(&sdev->resource[0], 0, - 0x10000UL, "soc xram"); - s->regs = sbus_ioremap(&sdev->resource[0], 0x10000UL, - 0x10UL, "soc regs"); - } else { - /* Probably SOC sbus card */ - s->xram = sbus_ioremap(&sdev->resource[1], 0, - sdev->reg_addrs[1].reg_size, "soc xram"); - s->regs = sbus_ioremap(&sdev->resource[2], 0, - sdev->reg_addrs[2].reg_size, "soc regs"); - } - - soc_init_bursts(s, sdev); - - SOD(("Disabling SOC\n")) - - soc_disable (s); - - irq = sdev->irqs[0]; - - if (request_irq (irq, soc_intr, IRQF_SHARED, "SOC", (void *)s)) { - soc_printk ("Cannot order irq %d to go\n", irq); - socs = s->next; - return; - } - - SOD(("SOC uses IRQ %d\n", irq)) - - s->port[0].fc.irq = irq; - s->port[1].fc.irq = irq; - - sprintf (s->port[0].fc.name, "soc%d port A", no); - sprintf (s->port[1].fc.name, "soc%d port B", no); - s->port[0].flags = SOC_FC_HDR | SOC_PORT_A; - s->port[1].flags = SOC_FC_HDR | SOC_PORT_B; - s->port[1].mask = (1 << 11); - - s->port[0].fc.hw_enque = soc_hw_enque; - s->port[1].fc.hw_enque = soc_hw_enque; - - soc_download_fw (s); - - SOD(("Downloaded firmware\n")) - - /* Now setup xram circular queues */ - memset (cq, 0, sizeof(cq)); - - size = (SOC_CQ_REQ0_SIZE + SOC_CQ_REQ1_SIZE) * sizeof(soc_req); - s->req_cpu = sbus_alloc_consistent(sdev, size, &s->req_dvma); - s->req[0].pool = s->req_cpu; - cq[0].address = s->req_dvma; - s->req[1].pool = s->req[0].pool + SOC_CQ_REQ0_SIZE; - - s->req[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET); - s->req[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq)); - s->rsp[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET); - s->rsp[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq)); - - cq[1].address = cq[0].address + (SOC_CQ_REQ0_SIZE * sizeof(soc_req)); - cq[4].address = 1; - cq[5].address = 1; - cq[0].last = SOC_CQ_REQ0_SIZE - 1; - cq[1].last = SOC_CQ_REQ1_SIZE - 1; - cq[4].last = SOC_CQ_RSP0_SIZE - 1; - cq[5].last = SOC_CQ_RSP1_SIZE - 1; - for (i = 0; i < 8; i++) - cq[i].seqno = 1; - - s->req[0].last = SOC_CQ_REQ0_SIZE - 1; - s->req[1].last = SOC_CQ_REQ1_SIZE - 1; - s->rsp[0].last = SOC_CQ_RSP0_SIZE - 1; - s->rsp[1].last = SOC_CQ_RSP1_SIZE - 1; - - s->req[0].seqno = 1; - s->req[1].seqno = 1; - s->rsp[0].seqno = 1; - s->rsp[1].seqno = 1; - - xram_copy_to (s->xram + SOC_CQ_REQ_OFFSET, cq, sizeof(cq)); - - /* Make our sw copy of SOC service parameters */ - xram_copy_from (s->serv_params, s->xram + 0x140, sizeof (s->serv_params)); - - s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params; - s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20); - s->port[1].fc.common_svc = (common_svc_parm *)&s->serv_params; - s->port[1].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20); - - soc_enable (s); - - SOD(("Enabled SOC\n")) -} - -static int __init soc_probe(void) -{ - struct sbus_bus *sbus; - struct sbus_dev *sdev = NULL; - struct soc *s; - int cards = 0; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if(!strcmp(sdev->prom_name, "SUNW,soc")) { - soc_init(sdev, cards); - cards++; - } - } - } - if (!cards) return -EIO; - - for_each_soc(s) - if (s->next) - s->port[1].fc.next = &s->next->port[0].fc; - fcp_init (&socs->port[0].fc); - return 0; -} - -static void __exit soc_cleanup(void) -{ - struct soc *s; - int irq; - struct sbus_dev *sdev; - - for_each_soc(s) { - irq = s->port[0].fc.irq; - free_irq (irq, s); - - fcp_release(&(s->port[0].fc), 2); - - sdev = s->port[0].fc.dev; - if (sdev->num_registers == 1) { - sbus_iounmap(s->xram, 0x10000UL); - sbus_iounmap(s->regs, 0x10UL); - } else { - sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size); - sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size); - } - sbus_free_consistent(sdev, - (SOC_CQ_REQ0_SIZE+SOC_CQ_REQ1_SIZE)*sizeof(soc_req), - s->req_cpu, s->req_dvma); - } -} - -module_init(soc_probe); -module_exit(soc_cleanup); -MODULE_LICENSE("GPL"); diff --git a/drivers/fc4/soc.h b/drivers/fc4/soc.h deleted file mode 100644 index d38cf5b..0000000 --- a/drivers/fc4/soc.h +++ /dev/null @@ -1,301 +0,0 @@ -/* soc.h: Definitions for Sparc SUNW,soc Fibre Channel Sbus driver. - * - * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#ifndef __SOC_H -#define __SOC_H - -#include "fc.h" -#include "fcp.h" -#include "fcp_impl.h" - -/* Hardware register offsets and constants first {{{ */ -#define CFG 0x00UL /* Config Register */ -#define SAE 0x04UL /* Slave Access Error Register */ -#define CMD 0x08UL /* Command and Status Register */ -#define IMASK 0x0cUL /* Interrupt Mask Register */ - -/* Config Register */ -#define SOC_CFG_EXT_RAM_BANK_MASK 0x07000000 -#define SOC_CFG_EEPROM_BANK_MASK 0x00030000 -#define SOC_CFG_BURST64_MASK 0x00000700 -#define SOC_CFG_SBUS_PARITY_TEST 0x00000020 -#define SOC_CFG_SBUS_PARITY_CHECK 0x00000010 -#define SOC_CFG_SBUS_ENHANCED 0x00000008 -#define SOC_CFG_BURST_MASK 0x00000007 -/* Bursts */ -#define SOC_CFG_BURST_4 0x00000000 -#define SOC_CFG_BURST_16 0x00000004 -#define SOC_CFG_BURST_32 0x00000005 -#define SOC_CFG_BURST_64 0x00000006 - -/* Slave Access Error Register */ -#define SOC_SAE_ALIGNMENT 0x00000004 -#define SOC_SAE_UNSUPPORTED 0x00000002 -#define SOC_SAE_PARITY 0x00000001 - -/* Command & Status Register */ -#define SOC_CMD_RSP_QALL 0x000f0000 -#define SOC_CMD_RSP_Q0 0x00010000 -#define SOC_CMD_RSP_Q1 0x00020000 -#define SOC_CMD_RSP_Q2 0x00040000 -#define SOC_CMD_RSP_Q3 0x00080000 -#define SOC_CMD_REQ_QALL 0x00000f00 -#define SOC_CMD_REQ_Q0 0x00000100 -#define SOC_CMD_REQ_Q1 0x00000200 -#define SOC_CMD_REQ_Q2 0x00000400 -#define SOC_CMD_REQ_Q3 0x00000800 -#define SOC_CMD_SAE 0x00000080 -#define SOC_CMD_INTR_PENDING 0x00000008 -#define SOC_CMD_NON_QUEUED 0x00000004 -#define SOC_CMD_IDLE 0x00000002 -#define SOC_CMD_SOFT_RESET 0x00000001 - -/* Interrupt Mask Register */ -#define SOC_IMASK_RSP_QALL 0x000f0000 -#define SOC_IMASK_RSP_Q0 0x00010000 -#define SOC_IMASK_RSP_Q1 0x00020000 -#define SOC_IMASK_RSP_Q2 0x00040000 -#define SOC_IMASK_RSP_Q3 0x00080000 -#define SOC_IMASK_REQ_QALL 0x00000f00 -#define SOC_IMASK_REQ_Q0 0x00000100 -#define SOC_IMASK_REQ_Q1 0x00000200 -#define SOC_IMASK_REQ_Q2 0x00000400 -#define SOC_IMASK_REQ_Q3 0x00000800 -#define SOC_IMASK_SAE 0x00000080 -#define SOC_IMASK_NON_QUEUED 0x00000004 - -#define SOC_INTR(s, cmd) \ - (((cmd & SOC_CMD_RSP_QALL) | ((~cmd) & SOC_CMD_REQ_QALL)) \ - & s->imask) - -#define SOC_SETIMASK(s, i) \ -do { (s)->imask = (i); \ - sbus_writel((i), (s)->regs + IMASK); \ -} while(0) - -/* XRAM - * - * This is a 64KB register area. It accepts only halfword access. - * That's why here are the following inline functions... - */ - -typedef void __iomem *xram_p; - -/* Get 32bit number from XRAM */ -static inline u32 xram_get_32(xram_p x) -{ - return ((sbus_readw(x + 0x00UL) << 16) | - (sbus_readw(x + 0x02UL))); -} - -/* Like the above, but when we don't care about the high 16 bits */ -static inline u32 xram_get_32low(xram_p x) -{ - return (u32) sbus_readw(x + 0x02UL); -} - -static inline u16 xram_get_16(xram_p x) -{ - return sbus_readw(x); -} - -static inline u8 xram_get_8(xram_p x) -{ - if ((unsigned long)x & 0x1UL) { - x = x - 1; - return (u8) sbus_readw(x); - } else { - return (u8) (sbus_readw(x) >> 8); - } -} - -static inline void xram_copy_from(void *p, xram_p x, int len) -{ - for (len >>= 2; len > 0; len--, x += sizeof(u32)) { - u32 val, *p32 = p; - - val = ((sbus_readw(x + 0x00UL) << 16) | - (sbus_readw(x + 0x02UL))); - *p32++ = val; - p = p32; - } -} - -static inline void xram_copy_to(xram_p x, void *p, int len) -{ - for (len >>= 2; len > 0; len--, x += sizeof(u32)) { - u32 tmp, *p32 = p; - - tmp = *p32++; - p = p32; - sbus_writew(tmp >> 16, x + 0x00UL); - sbus_writew(tmp, x + 0x02UL); - } -} - -static inline void xram_bzero(xram_p x, int len) -{ - for (len >>= 1; len > 0; len--, x += sizeof(u16)) - sbus_writew(0, x); -} - -/* Circular Queue */ - -#define SOC_CQ_REQ_OFFSET (0x100 * sizeof(u16)) -#define SOC_CQ_RSP_OFFSET (0x110 * sizeof(u16)) - -typedef struct { - u32 address; - u8 in; - u8 out; - u8 last; - u8 seqno; -} soc_hw_cq; - -#define SOC_PORT_A 0x0000 /* From/To Port A */ -#define SOC_PORT_B 0x0001 /* From/To Port A */ -#define SOC_FC_HDR 0x0002 /* Contains FC Header */ -#define SOC_NORSP 0x0004 /* Don't generate response nor interrupt */ -#define SOC_NOINT 0x0008 /* Generate response but not interrupt */ -#define SOC_XFERRDY 0x0010 /* Generate XFERRDY */ -#define SOC_IGNOREPARAM 0x0020 /* Ignore PARAM field in the FC header */ -#define SOC_COMPLETE 0x0040 /* Command completed */ -#define SOC_UNSOLICITED 0x0080 /* For request this is the packet to establish unsolicited pools, */ - /* for rsp this is unsolicited packet */ -#define SOC_STATUS 0x0100 /* State change (on/off line) */ - -typedef struct { - u32 token; - u16 flags; - u8 class; - u8 segcnt; - u32 bytecnt; -} soc_hdr; - -typedef struct { - u32 base; - u32 count; -} soc_data; - -#define SOC_CQTYPE_OUTBOUND 0x01 -#define SOC_CQTYPE_INBOUND 0x02 -#define SOC_CQTYPE_SIMPLE 0x03 -#define SOC_CQTYPE_IO_WRITE 0x04 -#define SOC_CQTYPE_IO_READ 0x05 -#define SOC_CQTYPE_UNSOLICITED 0x06 -#define SOC_CQTYPE_DIAG 0x07 -#define SOC_CQTYPE_OFFLINE 0x08 -#define SOC_CQTYPE_RESPONSE 0x10 -#define SOC_CQTYPE_INLINE 0x20 - -#define SOC_CQFLAGS_CONT 0x01 -#define SOC_CQFLAGS_FULL 0x02 -#define SOC_CQFLAGS_BADHDR 0x04 -#define SOC_CQFLAGS_BADPKT 0x08 - -typedef struct { - soc_hdr shdr; - soc_data data[3]; - fc_hdr fchdr; - u8 count; - u8 type; - u8 flags; - u8 seqno; -} soc_req; - -#define SOC_OK 0 -#define SOC_P_RJT 2 -#define SOC_F_RJT 3 -#define SOC_P_BSY 4 -#define SOC_F_BSY 5 -#define SOC_ONLINE 0x10 -#define SOC_OFFLINE 0x11 -#define SOC_TIMEOUT 0x12 -#define SOC_OVERRUN 0x13 -#define SOC_UNKOWN_CQ_TYPE 0x20 -#define SOC_BAD_SEG_CNT 0x21 -#define SOC_MAX_XCHG_EXCEEDED 0x22 -#define SOC_BAD_XID 0x23 -#define SOC_XCHG_BUSY 0x24 -#define SOC_BAD_POOL_ID 0x25 -#define SOC_INSUFFICIENT_CQES 0x26 -#define SOC_ALLOC_FAIL 0x27 -#define SOC_BAD_SID 0x28 -#define SOC_NO_SEG_INIT 0x29 - -typedef struct { - soc_hdr shdr; - u32 status; - soc_data data; - u8 xxx1[12]; - fc_hdr fchdr; - u8 count; - u8 type; - u8 flags; - u8 seqno; -} soc_rsp; - -/* }}} */ - -/* Now our software structures and constants we use to drive the beast {{{ */ - -#define SOC_CQ_REQ0_SIZE 4 -#define SOC_CQ_REQ1_SIZE 64 -#define SOC_CQ_RSP0_SIZE 8 -#define SOC_CQ_RSP1_SIZE 4 - -#define SOC_SOLICITED_RSP_Q 0 -#define SOC_UNSOLICITED_RSP_Q 1 - -struct soc; - -typedef struct { - /* This must come first */ - fc_channel fc; - struct soc *s; - u16 flags; - u16 mask; -} soc_port; - -typedef struct { - soc_hw_cq __iomem *hw_cq; /* Related XRAM cq */ - soc_req __iomem *pool; - u8 in; - u8 out; - u8 last; - u8 seqno; -} soc_cq_rsp; - -typedef struct { - soc_hw_cq __iomem *hw_cq; /* Related XRAM cq */ - soc_req *pool; - u8 in; - u8 out; - u8 last; - u8 seqno; -} soc_cq_req; - -struct soc { - spinlock_t lock; - soc_port port[2]; /* Every SOC has one or two FC ports */ - soc_cq_req req[2]; /* Request CQs */ - soc_cq_rsp rsp[2]; /* Response CQs */ - int soc_no; - void __iomem *regs; - xram_p xram; - fc_wwn wwn; - u32 imask; /* Our copy of regs->imask */ - u32 cfg; /* Our copy of regs->cfg */ - char serv_params[80]; - struct soc *next; - int curr_port; /* Which port will have priority to fcp_queue_empty */ - - soc_req *req_cpu; - u32 req_dvma; -}; - -/* }}} */ - -#endif /* !(__SOC_H) */ diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c deleted file mode 100644 index c903ebf..0000000 --- a/drivers/fc4/socal.c +++ /dev/null @@ -1,904 +0,0 @@ -/* socal.c: Sparc SUNW,socal (SOC+) Fibre Channel Sbus adapter support. - * - * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz) - * - * Sources: - * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994 - * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995 - * SOC+ Programming Guide 0.1 - * Fibre Channel Arbitrated Loop (FC-AL), dpANS rev. 4.5, 1995 - * - * Supported hardware: - * On-board SOC+ adapters of Ultra Enterprise servers and sun4d. - */ - -static char *version = - "socal.c: SOC+ driver v1.1 9/Feb/99 Jakub Jelinek (jj@ultra.linux.cz)\n"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* #define SOCALDEBUG */ -/* #define HAVE_SOCAL_UCODE */ -/* #define USE_64BIT_MODE */ - -#include "fcp_impl.h" -#include "socal.h" -#ifdef HAVE_SOCAL_UCODE -#include "socal_asm.h" -#endif - -#define socal_printk printk ("socal%d: ", s->socal_no); printk - -#ifdef SOCALDEBUG -#define SOD(x) socal_printk x; -#else -#define SOD(x) -#endif - -#define for_each_socal(s) for (s = socals; s; s = s->next) -struct socal *socals = NULL; - -static void socal_copy_from_xram(void *d, void __iomem *xram, long size) -{ - u32 *dp = (u32 *) d; - while (size) { - *dp++ = sbus_readl(xram); - xram += sizeof(u32); - size -= sizeof(u32); - } -} - -static void socal_copy_to_xram(void __iomem *xram, void *s, long size) -{ - u32 *sp = (u32 *) s; - while (size) { - u32 val = *sp++; - sbus_writel(val, xram); - xram += sizeof(u32); - size -= sizeof(u32); - } -} - -#ifdef HAVE_SOCAL_UCODE -static void socal_bzero(unsigned long xram, int size) -{ - while (size) { - sbus_writel(0, xram); - xram += sizeof(u32); - size -= sizeof(u32); - } -} -#endif - -static inline void socal_disable(struct socal *s) -{ - sbus_writel(0, s->regs + IMASK); - sbus_writel(SOCAL_CMD_SOFT_RESET, s->regs + CMD); -} - -static inline void socal_enable(struct socal *s) -{ - SOD(("enable %08x\n", s->cfg)) - sbus_writel(0, s->regs + SAE); - sbus_writel(s->cfg, s->regs + CFG); - sbus_writel(SOCAL_CMD_RSP_QALL, s->regs + CMD); - SOCAL_SETIMASK(s, SOCAL_IMASK_RSP_QALL | SOCAL_IMASK_SAE); - SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK))); -} - -static void socal_reset(fc_channel *fc) -{ - socal_port *port = (socal_port *)fc; - struct socal *s = port->s; - - /* FIXME */ - socal_disable(s); - s->req[0].seqno = 1; - s->req[1].seqno = 1; - s->rsp[0].seqno = 1; - s->rsp[1].seqno = 1; - s->req[0].in = 0; - s->req[1].in = 0; - s->rsp[0].in = 0; - s->rsp[1].in = 0; - s->req[0].out = 0; - s->req[1].out = 0; - s->rsp[0].out = 0; - s->rsp[1].out = 0; - - /* FIXME */ - socal_enable(s); -} - -static inline void socal_solicited(struct socal *s, unsigned long qno) -{ - socal_rsp *hwrsp; - socal_cq *sw_cq; - int token; - int status; - fc_channel *fc; - - sw_cq = &s->rsp[qno]; - - /* Finally an improvement against old SOC :) */ - sw_cq->in = sbus_readb(s->regs + RESP + qno); - SOD (("socal_solicited, %d packets arrived\n", - (sw_cq->in - sw_cq->out) & sw_cq->last)) - for (;;) { - hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out; - SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out)) - -#if defined(SOCALDEBUG) && 0 - { - u32 *u = (u32 *)hwrsp; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) - u += 8; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) - u = (u32 *)s->xram; - while (u < ((u32 *)s->regs)) { - if (sbus_readl(&u[0]) == 0x00003000 || - sbus_readl(&u[0]) == 0x00003801) { - SOD(("Found at %04lx\n", - (unsigned long)u - (unsigned long)s->xram)) - SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", - sbus_readl(&u[0]), sbus_readl(&u[1]), - sbus_readl(&u[2]), sbus_readl(&u[3]), - sbus_readl(&u[4]), sbus_readl(&u[5]), - sbus_readl(&u[6]), sbus_readl(&u[7]))) - u += 8; - SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", - sbus_readl(&u[0]), sbus_readl(&u[1]), - sbus_readl(&u[2]), sbus_readl(&u[3]), - sbus_readl(&u[4]), sbus_readl(&u[5]), - sbus_readl(&u[6]), sbus_readl(&u[7]))) - u -= 8; - } - u++; - } - } -#endif - - token = hwrsp->shdr.token; - status = hwrsp->status; - fc = (fc_channel *)(&s->port[(token >> 11) & 1]); - - SOD(("Solicited token %08x status %08x\n", token, status)) - if (status == SOCAL_OK) { - fcp_receive_solicited(fc, token >> 12, - token & ((1 << 11) - 1), - FC_STATUS_OK, NULL); - } else { - /* We have intentionally defined FC_STATUS_* constants - * to match SOCAL_* constants, otherwise we'd have to - * translate status. - */ - fcp_receive_solicited(fc, token >> 12, - token & ((1 << 11) - 1), status, &hwrsp->fchdr); - } - - if (++sw_cq->out > sw_cq->last) { - sw_cq->seqno++; - sw_cq->out = 0; - } - - if (sw_cq->out == sw_cq->in) { - sw_cq->in = sbus_readb(s->regs + RESP + qno); - if (sw_cq->out == sw_cq->in) { - /* Tell the hardware about it */ - sbus_writel((sw_cq->out << 24) | - (SOCAL_CMD_RSP_QALL & - ~(SOCAL_CMD_RSP_Q0 << qno)), - s->regs + CMD); - - /* Read it, so that we're sure it has been updated */ - sbus_readl(s->regs + CMD); - sw_cq->in = sbus_readb(s->regs + RESP + qno); - if (sw_cq->out == sw_cq->in) - break; - } - } - } -} - -static inline void socal_request (struct socal *s, u32 cmd) -{ - SOCAL_SETIMASK(s, s->imask & ~(cmd & SOCAL_CMD_REQ_QALL)); - SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK))); - - SOD(("Queues available %08x OUT %X\n", cmd, s->regs->reqpr[0])) - if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) { - fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port])); - if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out)) - fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); - } else { - fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port])); - } - if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE) - s->curr_port ^= 1; -} - -static inline void socal_unsolicited (struct socal *s, unsigned long qno) -{ - socal_rsp *hwrsp, *hwrspc; - socal_cq *sw_cq; - int count; - int status; - int flags; - fc_channel *fc; - - sw_cq = &s->rsp[qno]; - - sw_cq->in = sbus_readb(s->regs + RESP + qno); - SOD (("socal_unsolicited, %d packets arrived, in %d\n", - (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in)) - while (sw_cq->in != sw_cq->out) { - /* ...real work per entry here... */ - hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out; - SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out)) - -#if defined(SOCALDEBUG) && 0 - { - u32 *u = (u32 *)hwrsp; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) - u += 8; - SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7])) - } -#endif - - hwrspc = NULL; - flags = hwrsp->shdr.flags; - count = hwrsp->count; - fc = (fc_channel *)&s->port[flags & SOCAL_PORT_B]; - SOD(("FC %08lx\n", (long)fc)) - - if (count != 1) { - /* Ugh, continuation entries */ - u8 in; - - if (count != 2) { - printk("%s: Too many continuations entries %d\n", - fc->name, count); - goto update_out; - } - - in = sw_cq->in; - if (in < sw_cq->out) - in += sw_cq->last + 1; - if (in < sw_cq->out + 2) { - /* Ask the hardware if they haven't arrived yet. */ - sbus_writel((sw_cq->out << 24) | - (SOCAL_CMD_RSP_QALL & - ~(SOCAL_CMD_RSP_Q0 << qno)), - s->regs + CMD); - - /* Read it, so that we're sure it has been updated */ - sbus_readl(s->regs + CMD); - sw_cq->in = sbus_readb(s->regs + RESP + qno); - in = sw_cq->in; - if (in < sw_cq->out) - in += sw_cq->last + 1; - if (in < sw_cq->out + 2) /* Nothing came, let us wait */ - return; - } - if (sw_cq->out == sw_cq->last) - hwrspc = (socal_rsp *)sw_cq->pool; - else - hwrspc = hwrsp + 1; - } - - switch (flags & ~SOCAL_PORT_B) { - case SOCAL_STATUS: - status = hwrsp->status; - switch (status) { - case SOCAL_ONLINE: - SOD(("State change to ONLINE\n")); - fcp_state_change(fc, FC_STATE_ONLINE); - break; - case SOCAL_ONLINE_LOOP: - SOD(("State change to ONLINE_LOOP\n")); - fcp_state_change(fc, FC_STATE_ONLINE); - break; - case SOCAL_OFFLINE: - SOD(("State change to OFFLINE\n")); - fcp_state_change(fc, FC_STATE_OFFLINE); - break; - default: - printk ("%s: Unknown STATUS no %d\n", - fc->name, status); - break; - }; - - break; - case (SOCAL_UNSOLICITED|SOCAL_FC_HDR): - { - int r_ctl = *((u8 *)&hwrsp->fchdr); - unsigned len; - - if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) { - len = hwrsp->shdr.bytecnt; - if (len < 4 || !hwrspc) { - printk ("%s: Invalid R_CTL %02x " - "continuation entries\n", - fc->name, r_ctl); - } else { - if (len > 60) - len = 60; - if (*(u32 *)hwrspc == LS_DISPLAY) { - int i; - - for (i = 4; i < len; i++) - if (((u8 *)hwrspc)[i] == '\n') - ((u8 *)hwrspc)[i] = ' '; - ((u8 *)hwrspc)[len] = 0; - printk ("%s message: %s\n", - fc->name, ((u8 *)hwrspc) + 4); - } else { - printk ("%s: Unknown LS_CMD " - "%08x\n", fc->name, - *(u32 *)hwrspc); - } - } - } else { - printk ("%s: Unsolicited R_CTL %02x " - "not handled\n", fc->name, r_ctl); - } - } - break; - default: - printk ("%s: Unexpected flags %08x\n", fc->name, flags); - break; - }; -update_out: - if (++sw_cq->out > sw_cq->last) { - sw_cq->seqno++; - sw_cq->out = 0; - } - - if (hwrspc) { - if (++sw_cq->out > sw_cq->last) { - sw_cq->seqno++; - sw_cq->out = 0; - } - } - - if (sw_cq->out == sw_cq->in) { - sw_cq->in = sbus_readb(s->regs + RESP + qno); - if (sw_cq->out == sw_cq->in) { - /* Tell the hardware about it */ - sbus_writel((sw_cq->out << 24) | - (SOCAL_CMD_RSP_QALL & - ~(SOCAL_CMD_RSP_Q0 << qno)), - s->regs + CMD); - - /* Read it, so that we're sure it has been updated */ - sbus_readl(s->regs + CMD); - sw_cq->in = sbus_readb(s->regs + RESP + qno); - } - } - } -} - -static irqreturn_t socal_intr(int irq, void *dev_id) -{ - u32 cmd; - unsigned long flags; - register struct socal *s = (struct socal *)dev_id; - - spin_lock_irqsave(&s->lock, flags); - cmd = sbus_readl(s->regs + CMD); - for (; (cmd = SOCAL_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) { -#ifdef SOCALDEBUG - static int cnt = 0; - if (cnt++ < 50) - printk("soc_intr %08x\n", cmd); -#endif - if (cmd & SOCAL_CMD_RSP_Q2) - socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q); - if (cmd & SOCAL_CMD_RSP_Q1) - socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q); - if (cmd & SOCAL_CMD_RSP_Q0) - socal_solicited (s, SOCAL_SOLICITED_RSP_Q); - if (cmd & SOCAL_CMD_REQ_QALL) - socal_request (s, cmd); - } - spin_unlock_irqrestore(&s->lock, flags); - - return IRQ_HANDLED; -} - -#define TOKEN(proto, port, token) (((proto)<<12)|(token)|(port)) - -static int socal_hw_enque (fc_channel *fc, fcp_cmnd *fcmd) -{ - socal_port *port = (socal_port *)fc; - struct socal *s = port->s; - unsigned long qno; - socal_cq *sw_cq; - int cq_next_in; - socal_req *request; - fc_hdr *fch; - int i; - - if (fcmd->proto == TYPE_SCSI_FCP) - qno = 1; - else - qno = 0; - SOD(("Putting a FCP packet type %d into hw queue %d\n", fcmd->proto, qno)) - if (s->imask & (SOCAL_IMASK_REQ_Q0 << qno)) { - SOD(("EIO %08x\n", s->imask)) - return -EIO; - } - sw_cq = s->req + qno; - cq_next_in = (sw_cq->in + 1) & sw_cq->last; - - if (cq_next_in == sw_cq->out && - cq_next_in == (sw_cq->out = sbus_readb(s->regs + REQP + qno))) { - SOD(("%d IN %d OUT %d LAST %d\n", - qno, sw_cq->in, - sw_cq->out, sw_cq->last)) - SOCAL_SETIMASK(s, s->imask | (SOCAL_IMASK_REQ_Q0 << qno)); - SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK))); - - /* If queue is full, just say NO. */ - return -EBUSY; - } - - request = sw_cq->pool + sw_cq->in; - fch = &request->fchdr; - - switch (fcmd->proto) { - case TYPE_SCSI_FCP: - request->shdr.token = TOKEN(TYPE_SCSI_FCP, port->mask, fcmd->token); - request->data[0].base = fc->dma_scsi_cmd + fcmd->token * sizeof(fcp_cmd); - request->data[0].count = sizeof(fcp_cmd); - request->data[1].base = fc->dma_scsi_rsp + fcmd->token * fc->rsp_size; - request->data[1].count = fc->rsp_size; - if (fcmd->data) { - request->shdr.segcnt = 3; - i = fc->scsi_cmd_pool[fcmd->token].fcp_data_len; - request->shdr.bytecnt = i; - request->data[2].base = fcmd->data; - request->data[2].count = i; - request->type = (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ? - SOCAL_CQTYPE_IO_WRITE : SOCAL_CQTYPE_IO_READ; - } else { - request->shdr.segcnt = 2; - request->shdr.bytecnt = 0; - request->data[2].base = 0; - request->data[2].count = 0; - request->type = SOCAL_CQTYPE_SIMPLE; - } - FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fcmd->did); - FILL_FCHDR_SID(fch, fc->sid); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); - fch->param = 0; - request->shdr.flags = port->flags; - request->shdr.class = fc->posmap ? 3 : 2; - break; - - case PROTO_OFFLINE: - memset (request, 0, sizeof(*request)); - request->shdr.token = TOKEN(PROTO_OFFLINE, port->mask, fcmd->token); - request->type = SOCAL_CQTYPE_OFFLINE; - FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fcmd->did); - FILL_FCHDR_SID(fch, fc->sid); - FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE); - FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0); - FILL_FCHDR_OXRX(fch, 0xffff, 0xffff); - request->shdr.flags = port->flags; - break; - - case PROTO_REPORT_AL_MAP: - memset (request, 0, sizeof(*request)); - request->shdr.token = TOKEN(PROTO_REPORT_AL_MAP, port->mask, fcmd->token); - request->type = SOCAL_CQTYPE_REPORT_MAP; - request->shdr.flags = port->flags; - request->shdr.segcnt = 1; - request->shdr.bytecnt = sizeof(fc_al_posmap); - request->data[0].base = fcmd->cmd; - request->data[0].count = sizeof(fc_al_posmap); - break; - - default: - request->shdr.token = TOKEN(fcmd->proto, port->mask, fcmd->token); - request->shdr.class = fc->posmap ? 3 : 2; - request->shdr.flags = port->flags; - memcpy (fch, &fcmd->fch, sizeof(fc_hdr)); - request->data[0].count = fcmd->cmdlen; - request->data[1].count = fcmd->rsplen; - request->type = fcmd->class; - switch (fcmd->class) { - case FC_CLASS_OUTBOUND: - request->data[0].base = fcmd->cmd; - request->data[0].count = fcmd->cmdlen; - request->type = SOCAL_CQTYPE_OUTBOUND; - request->shdr.bytecnt = fcmd->cmdlen; - request->shdr.segcnt = 1; - break; - case FC_CLASS_INBOUND: - request->data[0].base = fcmd->rsp; - request->data[0].count = fcmd->rsplen; - request->type = SOCAL_CQTYPE_INBOUND; - request->shdr.bytecnt = 0; - request->shdr.segcnt = 1; - break; - case FC_CLASS_SIMPLE: - request->data[0].base = fcmd->cmd; - request->data[1].base = fcmd->rsp; - request->data[0].count = fcmd->cmdlen; - request->data[1].count = fcmd->rsplen; - request->type = SOCAL_CQTYPE_SIMPLE; - request->shdr.bytecnt = fcmd->cmdlen; - request->shdr.segcnt = 2; - break; - case FC_CLASS_IO_READ: - case FC_CLASS_IO_WRITE: - request->data[0].base = fcmd->cmd; - request->data[1].base = fcmd->rsp; - request->data[0].count = fcmd->cmdlen; - request->data[1].count = fcmd->rsplen; - request->type = (fcmd->class == FC_CLASS_IO_READ) ? SOCAL_CQTYPE_IO_READ : SOCAL_CQTYPE_IO_WRITE; - if (fcmd->data) { - request->data[2].base = fcmd->data; - request->data[2].count = fcmd->datalen; - request->shdr.bytecnt = fcmd->datalen; - request->shdr.segcnt = 3; - } else { - request->shdr.bytecnt = 0; - request->shdr.segcnt = 2; - } - break; - } - break; - } - - request->count = 1; - request->flags = 0; - request->seqno = sw_cq->seqno; - - SOD(("queueing token %08x\n", request->shdr.token)) - - /* And now tell the SOCAL about it */ - - if (++sw_cq->in > sw_cq->last) { - sw_cq->in = 0; - sw_cq->seqno++; - } - - SOD(("Putting %08x into cmd\n", SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno))) - - sbus_writel(SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno), - s->regs + CMD); - - /* Read so that command is completed */ - sbus_readl(s->regs + CMD); - - return 0; -} - -static inline void socal_download_fw(struct socal *s) -{ -#ifdef HAVE_SOCAL_UCODE - SOD(("Loading %ld bytes from %p to %p\n", sizeof(socal_ucode), socal_ucode, s->xram)) - socal_copy_to_xram(s->xram, socal_ucode, sizeof(socal_ucode)); - SOD(("Clearing the rest of memory\n")) - socal_bzero (s->xram + sizeof(socal_ucode), 65536 - sizeof(socal_ucode)); - SOD(("Done\n")) -#endif -} - -/* Check for what the best SBUS burst we can use happens - * to be on this machine. - */ -static inline void socal_init_bursts(struct socal *s, struct sbus_dev *sdev) -{ - int bsizes, bsizes_more; - u32 cfg; - - bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff); - bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff); - bsizes &= bsizes_more; -#ifdef USE_64BIT_MODE -#ifdef __sparc_v9__ - mmu_set_sbus64(sdev, bsizes >> 16); -#endif -#endif - if ((bsizes & 0x7f) == 0x7f) - cfg = SOCAL_CFG_BURST_64; - else if ((bsizes & 0x3f) == 0x3f) - cfg = SOCAL_CFG_BURST_32; - else if ((bsizes & 0x1f) == 0x1f) - cfg = SOCAL_CFG_BURST_16; - else - cfg = SOCAL_CFG_BURST_4; -#ifdef USE_64BIT_MODE -#ifdef __sparc_v9__ - /* What is BURST_128? -jj */ - if ((bsizes & 0x780000) == 0x780000) - cfg |= (SOCAL_CFG_BURST_64 << 8) | SOCAL_CFG_SBUS_ENHANCED; - else if ((bsizes & 0x380000) == 0x380000) - cfg |= (SOCAL_CFG_BURST_32 << 8) | SOCAL_CFG_SBUS_ENHANCED; - else if ((bsizes & 0x180000) == 0x180000) - cfg |= (SOCAL_CFG_BURST_16 << 8) | SOCAL_CFG_SBUS_ENHANCED; - else - cfg |= (SOCAL_CFG_BURST_8 << 8) | SOCAL_CFG_SBUS_ENHANCED; -#endif -#endif - s->cfg = cfg; -} - -static inline void socal_init(struct sbus_dev *sdev, int no) -{ - unsigned char tmp[60]; - int propl; - struct socal *s; - static unsigned version_printed = 0; - socal_hw_cq cq[8]; - int size, i; - int irq, node; - - s = kzalloc (sizeof (struct socal), GFP_KERNEL); - if (!s) return; - spin_lock_init(&s->lock); - s->socal_no = no; - - SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n", - (long)socals, (long)socal_intr, (long)socal_hw_enque)) - if (version_printed++ == 0) - printk (version); - - s->port[0].fc.module = THIS_MODULE; - s->port[1].fc.module = THIS_MODULE; - - s->next = socals; - socals = s; - s->port[0].fc.dev = sdev; - s->port[1].fc.dev = sdev; - s->port[0].s = s; - s->port[1].s = s; - - s->port[0].fc.next = &s->port[1].fc; - - /* World Wide Name of SOCAL */ - propl = prom_getproperty (sdev->prom_node, "wwn", tmp, sizeof(tmp)); - if (propl != sizeof (fc_wwn)) { - s->wwn.naaid = NAAID_IEEE_REG; - s->wwn.nportid = 0x123; - s->wwn.hi = 0x1234; - s->wwn.lo = 0x12345678; - } else - memcpy (&s->wwn, tmp, sizeof (fc_wwn)); - - memcpy (&s->port[0].fc.wwn_nport, &s->wwn, sizeof (fc_wwn)); - s->port[0].fc.wwn_nport.lo++; - memcpy (&s->port[1].fc.wwn_nport, &s->wwn, sizeof (fc_wwn)); - s->port[1].fc.wwn_nport.lo+=2; - - node = prom_getchild (sdev->prom_node); - while (node && (node = prom_searchsiblings (node, "sf"))) { - int port; - - port = prom_getintdefault(node, "port#", -1); - switch (port) { - case 0: - case 1: - if (prom_getproplen(node, "port-wwn") == sizeof (fc_wwn)) - prom_getproperty (node, "port-wwn", - (char *)&s->port[port].fc.wwn_nport, - sizeof (fc_wwn)); - break; - default: - break; - }; - - node = prom_getsibling(node); - } - - memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); - memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn)); - SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n", - *(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo, - *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo, - *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo)) - - s->port[0].fc.sid = 1; - s->port[1].fc.sid = 17; - s->port[0].fc.did = 2; - s->port[1].fc.did = 18; - - s->port[0].fc.reset = socal_reset; - s->port[1].fc.reset = socal_reset; - - if (sdev->num_registers == 1) { - s->eeprom = sbus_ioremap(&sdev->resource[0], 0, - sdev->reg_addrs[0].reg_size, "socal xram"); - if (sdev->reg_addrs[0].reg_size > 0x20000) - s->xram = s->eeprom + 0x10000UL; - else - s->xram = s->eeprom; - s->regs = (s->xram + 0x10000UL); - } else { - /* E.g. starfire presents 3 registers for SOCAL */ - s->xram = sbus_ioremap(&sdev->resource[1], 0, - sdev->reg_addrs[1].reg_size, "socal xram"); - s->regs = sbus_ioremap(&sdev->resource[2], 0, - sdev->reg_addrs[2].reg_size, "socal regs"); - } - - socal_init_bursts(s, sdev); - - SOD(("Disabling SOCAL\n")) - - socal_disable (s); - - irq = sdev->irqs[0]; - - if (request_irq (irq, socal_intr, IRQF_SHARED, "SOCAL", (void *)s)) { - socal_printk ("Cannot order irq %d to go\n", irq); - socals = s->next; - return; - } - - SOD(("SOCAL uses IRQ %d\n", irq)) - - s->port[0].fc.irq = irq; - s->port[1].fc.irq = irq; - - sprintf (s->port[0].fc.name, "socal%d port A", no); - sprintf (s->port[1].fc.name, "socal%d port B", no); - s->port[0].flags = SOCAL_FC_HDR | SOCAL_PORT_A; - s->port[1].flags = SOCAL_FC_HDR | SOCAL_PORT_B; - s->port[1].mask = (1 << 11); - - s->port[0].fc.hw_enque = socal_hw_enque; - s->port[1].fc.hw_enque = socal_hw_enque; - - socal_download_fw (s); - - SOD(("Downloaded firmware\n")) - - /* Now setup xram circular queues */ - memset (cq, 0, sizeof(cq)); - - size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE + - SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE + - SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req); - s->req_cpu = sbus_alloc_consistent(sdev, size, &s->req_dvma); - s->req[0].pool = s->req_cpu; - cq[0].address = s->req_dvma; - s->req[1].pool = s->req[0].pool + SOCAL_CQ_REQ0_SIZE; - s->rsp[0].pool = s->req[1].pool + SOCAL_CQ_REQ1_SIZE; - s->rsp[1].pool = s->rsp[0].pool + SOCAL_CQ_RSP0_SIZE; - s->rsp[2].pool = s->rsp[1].pool + SOCAL_CQ_RSP1_SIZE; - - s->req[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET); - s->req[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET + sizeof(socal_hw_cq)); - s->rsp[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET); - s->rsp[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + sizeof(socal_hw_cq)); - s->rsp[2].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + 2 * sizeof(socal_hw_cq)); - - cq[1].address = cq[0].address + (SOCAL_CQ_REQ0_SIZE * sizeof(socal_req)); - cq[4].address = cq[1].address + (SOCAL_CQ_REQ1_SIZE * sizeof(socal_req)); - cq[5].address = cq[4].address + (SOCAL_CQ_RSP0_SIZE * sizeof(socal_req)); - cq[6].address = cq[5].address + (SOCAL_CQ_RSP1_SIZE * sizeof(socal_req)); - - cq[0].last = SOCAL_CQ_REQ0_SIZE - 1; - cq[1].last = SOCAL_CQ_REQ1_SIZE - 1; - cq[4].last = SOCAL_CQ_RSP0_SIZE - 1; - cq[5].last = SOCAL_CQ_RSP1_SIZE - 1; - cq[6].last = SOCAL_CQ_RSP2_SIZE - 1; - for (i = 0; i < 8; i++) - cq[i].seqno = 1; - - s->req[0].last = SOCAL_CQ_REQ0_SIZE - 1; - s->req[1].last = SOCAL_CQ_REQ1_SIZE - 1; - s->rsp[0].last = SOCAL_CQ_RSP0_SIZE - 1; - s->rsp[1].last = SOCAL_CQ_RSP1_SIZE - 1; - s->rsp[2].last = SOCAL_CQ_RSP2_SIZE - 1; - - s->req[0].seqno = 1; - s->req[1].seqno = 1; - s->rsp[0].seqno = 1; - s->rsp[1].seqno = 1; - s->rsp[2].seqno = 1; - - socal_copy_to_xram(s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq)); - - SOD(("Setting up params\n")) - - /* Make our sw copy of SOCAL service parameters */ - socal_copy_from_xram(s->serv_params, s->xram + 0x280, sizeof (s->serv_params)); - - s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params; - s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20); - s->port[1].fc.common_svc = (common_svc_parm *)&s->serv_params; - s->port[1].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20); - - socal_enable (s); - - SOD(("Enabled SOCAL\n")) -} - -static int __init socal_probe(void) -{ - struct sbus_bus *sbus; - struct sbus_dev *sdev = NULL; - struct socal *s; - int cards = 0; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if(!strcmp(sdev->prom_name, "SUNW,socal")) { - socal_init(sdev, cards); - cards++; - } - } - } - if (!cards) - return -EIO; - - for_each_socal(s) - if (s->next) - s->port[1].fc.next = &s->next->port[0].fc; - - fcp_init (&socals->port[0].fc); - return 0; -} - -static void __exit socal_cleanup(void) -{ - struct socal *s; - int irq; - struct sbus_dev *sdev; - - for_each_socal(s) { - irq = s->port[0].fc.irq; - free_irq (irq, s); - - fcp_release(&(s->port[0].fc), 2); - - sdev = s->port[0].fc.dev; - if (sdev->num_registers == 1) { - sbus_iounmap(s->eeprom, sdev->reg_addrs[0].reg_size); - } else { - sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size); - sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size); - } - sbus_free_consistent(sdev, - (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE + - SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE + - SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req), - s->req_cpu, s->req_dvma); - } -} - -module_init(socal_probe); -module_exit(socal_cleanup); -MODULE_LICENSE("GPL"); diff --git a/drivers/fc4/socal.h b/drivers/fc4/socal.h deleted file mode 100644 index 774edf6..0000000 --- a/drivers/fc4/socal.h +++ /dev/null @@ -1,314 +0,0 @@ -/* socal.h: Definitions for Sparc SUNW,socal (SOC+) Fibre Channel Sbus driver. - * - * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#ifndef __SOCAL_H -#define __SOCAL_H - -#include "fc.h" -#include "fcp.h" -#include "fcp_impl.h" - -/* Hardware register offsets and constants first {{{ */ -#define CFG 0x00UL -#define SAE 0x04UL -#define CMD 0x08UL -#define IMASK 0x0cUL -#define REQP 0x10UL -#define RESP 0x14UL - -/* Config Register */ -#define SOCAL_CFG_EXT_RAM_BANK_MASK 0x07000000 -#define SOCAL_CFG_EEPROM_BANK_MASK 0x00030000 -#define SOCAL_CFG_BURST64_MASK 0x00000700 -#define SOCAL_CFG_SBUS_PARITY_TEST 0x00000020 -#define SOCAL_CFG_SBUS_PARITY_CHECK 0x00000010 -#define SOCAL_CFG_SBUS_ENHANCED 0x00000008 -#define SOCAL_CFG_BURST_MASK 0x00000007 -/* Bursts */ -#define SOCAL_CFG_BURST_4 0x00000000 -#define SOCAL_CFG_BURST_8 0x00000003 -#define SOCAL_CFG_BURST_16 0x00000004 -#define SOCAL_CFG_BURST_32 0x00000005 -#define SOCAL_CFG_BURST_64 0x00000006 -#define SOCAL_CFG_BURST_128 0x00000007 - -/* Slave Access Error Register */ -#define SOCAL_SAE_ALIGNMENT 0x00000004 -#define SOCAL_SAE_UNSUPPORTED 0x00000002 -#define SOCAL_SAE_PARITY 0x00000001 - -/* Command & Status Register */ -#define SOCAL_CMD_RSP_QALL 0x000f0000 -#define SOCAL_CMD_RSP_Q0 0x00010000 -#define SOCAL_CMD_RSP_Q1 0x00020000 -#define SOCAL_CMD_RSP_Q2 0x00040000 -#define SOCAL_CMD_RSP_Q3 0x00080000 -#define SOCAL_CMD_REQ_QALL 0x00000f00 -#define SOCAL_CMD_REQ_Q0 0x00000100 -#define SOCAL_CMD_REQ_Q1 0x00000200 -#define SOCAL_CMD_REQ_Q2 0x00000400 -#define SOCAL_CMD_REQ_Q3 0x00000800 -#define SOCAL_CMD_SAE 0x00000080 -#define SOCAL_CMD_INTR_PENDING 0x00000008 -#define SOCAL_CMD_NON_QUEUED 0x00000004 -#define SOCAL_CMD_IDLE 0x00000002 -#define SOCAL_CMD_SOFT_RESET 0x00000001 - -/* Interrupt Mask Register */ -#define SOCAL_IMASK_RSP_QALL 0x000f0000 -#define SOCAL_IMASK_RSP_Q0 0x00010000 -#define SOCAL_IMASK_RSP_Q1 0x00020000 -#define SOCAL_IMASK_RSP_Q2 0x00040000 -#define SOCAL_IMASK_RSP_Q3 0x00080000 -#define SOCAL_IMASK_REQ_QALL 0x00000f00 -#define SOCAL_IMASK_REQ_Q0 0x00000100 -#define SOCAL_IMASK_REQ_Q1 0x00000200 -#define SOCAL_IMASK_REQ_Q2 0x00000400 -#define SOCAL_IMASK_REQ_Q3 0x00000800 -#define SOCAL_IMASK_SAE 0x00000080 -#define SOCAL_IMASK_NON_QUEUED 0x00000004 - -#define SOCAL_INTR(s, cmd) \ - (((cmd & SOCAL_CMD_RSP_QALL) | ((~cmd) & SOCAL_CMD_REQ_QALL)) \ - & s->imask) - -#define SOCAL_SETIMASK(s, i) \ -do { (s)->imask = (i); \ - sbus_writel((i), (s)->regs + IMASK); \ -} while (0) - -#define SOCAL_MAX_EXCHANGES 1024 - -/* XRAM - * - * This is a 64KB register area. - * From the documentation, it seems like it is finally able to cope - * at least with 1,2,4 byte accesses for read and 2,4 byte accesses for write. - */ - -/* Circular Queue */ - -#define SOCAL_CQ_REQ_OFFSET 0x200 -#define SOCAL_CQ_RSP_OFFSET 0x220 - -typedef struct { - u32 address; - u8 in; - u8 out; - u8 last; - u8 seqno; -} socal_hw_cq; - -#define SOCAL_PORT_A 0x0000 /* From/To Port A */ -#define SOCAL_PORT_B 0x0001 /* From/To Port A */ -#define SOCAL_FC_HDR 0x0002 /* Contains FC Header */ -#define SOCAL_NORSP 0x0004 /* Don't generate response nor interrupt */ -#define SOCAL_NOINT 0x0008 /* Generate response but not interrupt */ -#define SOCAL_XFERRDY 0x0010 /* Generate XFERRDY */ -#define SOCAL_IGNOREPARAM 0x0020 /* Ignore PARAM field in the FC header */ -#define SOCAL_COMPLETE 0x0040 /* Command completed */ -#define SOCAL_UNSOLICITED 0x0080 /* For request this is the packet to establish unsolicited pools, */ - /* for rsp this is unsolicited packet */ -#define SOCAL_STATUS 0x0100 /* State change (on/off line) */ -#define SOCAL_RSP_HDR 0x0200 /* Return frame header in any case */ - -typedef struct { - u32 token; - u16 flags; - u8 class; - u8 segcnt; - u32 bytecnt; -} socal_hdr; - -typedef struct { - u32 base; - u32 count; -} socal_data; - -#define SOCAL_CQTYPE_NOP 0x00 -#define SOCAL_CQTYPE_OUTBOUND 0x01 -#define SOCAL_CQTYPE_INBOUND 0x02 -#define SOCAL_CQTYPE_SIMPLE 0x03 -#define SOCAL_CQTYPE_IO_WRITE 0x04 -#define SOCAL_CQTYPE_IO_READ 0x05 -#define SOCAL_CQTYPE_UNSOLICITED 0x06 -#define SOCAL_CQTYPE_BYPASS_DEV 0x06 -#define SOCAL_CQTYPE_DIAG 0x07 -#define SOCAL_CQTYPE_OFFLINE 0x08 -#define SOCAL_CQTYPE_ADD_POOL 0x09 -#define SOCAL_CQTYPE_DELETE_POOL 0x0a -#define SOCAL_CQTYPE_ADD_BUFFER 0x0b -#define SOCAL_CQTYPE_ADD_POOL_BUFFER 0x0c -#define SOCAL_CQTYPE_REQUEST_ABORT 0x0d -#define SOCAL_CQTYPE_REQUEST_LIP 0x0e -#define SOCAL_CQTYPE_REPORT_MAP 0x0f -#define SOCAL_CQTYPE_RESPONSE 0x10 -#define SOCAL_CQTYPE_INLINE 0x20 - -#define SOCAL_CQFLAGS_CONT 0x01 -#define SOCAL_CQFLAGS_FULL 0x02 -#define SOCAL_CQFLAGS_BADHDR 0x04 -#define SOCAL_CQFLAGS_BADPKT 0x08 - -typedef struct { - socal_hdr shdr; - socal_data data[3]; - fc_hdr fchdr; - u8 count; - u8 type; - u8 flags; - u8 seqno; -} socal_req; - -#define SOCAL_OK 0 -#define SOCAL_P_RJT 2 -#define SOCAL_F_RJT 3 -#define SOCAL_P_BSY 4 -#define SOCAL_F_BSY 5 -#define SOCAL_ONLINE 0x10 -#define SOCAL_OFFLINE 0x11 -#define SOCAL_TIMEOUT 0x12 -#define SOCAL_OVERRUN 0x13 -#define SOCAL_ONLINE_LOOP 0x14 -#define SOCAL_OLD_PORT 0x15 -#define SOCAL_AL_PORT 0x16 -#define SOCAL_UNKOWN_CQ_TYPE 0x20 -#define SOCAL_BAD_SEG_CNT 0x21 -#define SOCAL_MAX_XCHG_EXCEEDED 0x22 -#define SOCAL_BAD_XID 0x23 -#define SOCAL_XCHG_BUSY 0x24 -#define SOCAL_BAD_POOL_ID 0x25 -#define SOCAL_INSUFFICIENT_CQES 0x26 -#define SOCAL_ALLOC_FAIL 0x27 -#define SOCAL_BAD_SID 0x28 -#define SOCAL_NO_SEG_INIT 0x29 -#define SOCAL_BAD_DID 0x2a -#define SOCAL_ABORTED 0x30 -#define SOCAL_ABORT_FAILED 0x31 - -typedef struct { - socal_hdr shdr; - u32 status; - socal_data data; - u8 xxx1[10]; - u16 ncmds; - fc_hdr fchdr; - u8 count; - u8 type; - u8 flags; - u8 seqno; -} socal_rsp; - -typedef struct { - socal_hdr shdr; - u8 xxx1[48]; - u8 count; - u8 type; - u8 flags; - u8 seqno; -} socal_cmdonly; - -#define SOCAL_DIAG_NOP 0x00 -#define SOCAL_DIAG_INT_LOOP 0x01 -#define SOCAL_DIAG_EXT_LOOP 0x02 -#define SOCAL_DIAG_REM_LOOP 0x03 -#define SOCAL_DIAG_XRAM_TEST 0x04 -#define SOCAL_DIAG_SOC_TEST 0x05 -#define SOCAL_DIAG_HCB_TEST 0x06 -#define SOCAL_DIAG_SOCLB_TEST 0x07 -#define SOCAL_DIAG_SRDSLB_TEST 0x08 -#define SOCAL_DIAG_EXTOE_TEST 0x09 - -typedef struct { - socal_hdr shdr; - u32 cmd; - u8 xxx1[44]; - u8 count; - u8 type; - u8 flags; - u8 seqno; -} socal_diag_req; - -#define SOCAL_POOL_MASK_RCTL 0x800000 -#define SOCAL_POOL_MASK_DID 0x700000 -#define SOCAL_POOL_MASK_SID 0x070000 -#define SOCAL_POOL_MASK_TYPE 0x008000 -#define SOCAL_POOL_MASK_F_CTL 0x007000 -#define SOCAL_POOL_MASK_SEQ_ID 0x000800 -#define SOCAL_POOL_MASK_D_CTL 0x000400 -#define SOCAL_POOL_MASK_SEQ_CNT 0x000300 -#define SOCAL_POOL_MASK_OX_ID 0x0000f0 -#define SOCAL_POOL_MASK_PARAM 0x00000f - -typedef struct { - socal_hdr shdr; - u32 pool_id; - u32 header_mask; - u32 buf_size; - u32 entries; - u8 xxx1[8]; - fc_hdr fchdr; - u8 count; - u8 type; - u8 flags; - u8 seqno; -} socal_pool_req; - -/* }}} */ - -/* Now our software structures and constants we use to drive the beast {{{ */ - -#define SOCAL_CQ_REQ0_SIZE 4 -#define SOCAL_CQ_REQ1_SIZE 256 -#define SOCAL_CQ_RSP0_SIZE 8 -#define SOCAL_CQ_RSP1_SIZE 4 -#define SOCAL_CQ_RSP2_SIZE 4 - -#define SOCAL_SOLICITED_RSP_Q 0 -#define SOCAL_SOLICITED_BAD_RSP_Q 1 -#define SOCAL_UNSOLICITED_RSP_Q 2 - -struct socal; - -typedef struct { - /* This must come first */ - fc_channel fc; - struct socal *s; - u16 flags; - u16 mask; -} socal_port; - -typedef struct { - socal_hw_cq __iomem *hw_cq; /* Related XRAM cq */ - socal_req *pool; - u8 in; - u8 out; - u8 last; - u8 seqno; -} socal_cq; - -struct socal { - spinlock_t lock; - socal_port port[2]; /* Every SOCAL has one or two FC ports */ - socal_cq req[4]; /* Request CQs */ - socal_cq rsp[4]; /* Response CQs */ - int socal_no; - void __iomem *regs; - void __iomem *xram; - void __iomem *eeprom; - fc_wwn wwn; - u32 imask; /* Our copy of regs->imask */ - u32 cfg; /* Our copy of regs->cfg */ - char serv_params[80]; - struct socal *next; - int curr_port; /* Which port will have priority to fcp_queue_empty */ - - socal_req * req_cpu; - u32 req_dvma; -}; - -/* }}} */ - -#endif /* !(__SOCAL_H) */ diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 6141389..2e6129f 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -115,7 +115,6 @@ obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o obj-$(CONFIG_SCSI_MESH) += mesh.o obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o -obj-$(CONFIG_SCSI_PLUTO) += pluto.o obj-$(CONFIG_SCSI_DECNCR) += NCR53C9x.o dec_esp.o obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o @@ -123,7 +122,6 @@ obj-$(CONFIG_SCSI_PPA) += ppa.o obj-$(CONFIG_SCSI_IMM) += imm.o obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o -obj-$(CONFIG_SCSI_FCAL) += fcal.o obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c deleted file mode 100644 index c4e16c0..0000000 --- a/drivers/scsi/fcal.c +++ /dev/null @@ -1,317 +0,0 @@ -/* fcal.c: Fibre Channel Arbitrated Loop SCSI host adapter driver. - * - * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_KMOD -#include -#endif - -#include - -#include "scsi.h" -#include -#include "../fc4/fcp_impl.h" -#include "fcal.h" - -#include - -/* #define FCAL_DEBUG */ - -#define fcal_printk printk ("FCAL %s: ", fc->name); printk - -#ifdef FCAL_DEBUG -#define FCALD(x) fcal_printk x; -#define FCALND(x) printk ("FCAL: "); printk x; -#else -#define FCALD(x) -#define FCALND(x) -#endif - -static unsigned char alpa2target[] = { -0x7e, 0x7d, 0x7c, 0xff, 0x7b, 0xff, 0xff, 0xff, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79, -0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x77, 0x76, 0xff, 0xff, 0x75, 0xff, 0x74, 0x73, 0x72, -0xff, 0xff, 0xff, 0x71, 0xff, 0x70, 0x6f, 0x6e, 0xff, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0xff, -0xff, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0xff, 0xff, 0x61, 0x60, 0xff, 0x5f, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0x5e, 0xff, 0x5d, 0x5c, 0x5b, 0xff, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0xff, -0xff, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0xff, 0xff, 0x4e, 0x4d, 0xff, 0x4c, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0x4b, 0xff, 0x4a, 0x49, 0x48, 0xff, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0xff, -0xff, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0xff, 0xff, 0x3b, 0x3a, 0xff, 0x39, 0xff, 0xff, 0xff, -0x38, 0x37, 0x36, 0xff, 0x35, 0xff, 0xff, 0xff, 0x34, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33, -0x32, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x30, 0xff, 0xff, 0x2f, 0xff, 0x2e, 0x2d, 0x2c, -0xff, 0xff, 0xff, 0x2b, 0xff, 0x2a, 0x29, 0x28, 0xff, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0xff, -0xff, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0xff, 0xff, 0x1b, 0x1a, 0xff, 0x19, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0x18, 0xff, 0x17, 0x16, 0x15, 0xff, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0xff, -0xff, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0xff, 0xff, 0x08, 0x07, 0xff, 0x06, 0xff, 0xff, 0xff, -0x05, 0x04, 0x03, 0xff, 0x02, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 -}; - -static unsigned char target2alpa[] = { -0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, -0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3, -0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, -0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73, -0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56, -0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, -0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26, -0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00 -}; - -static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd); - -int fcal_slave_configure(struct scsi_device *device) -{ - int depth_to_use; - - if (device->tagged_supported) - depth_to_use = /* 254 */ 8; - else - depth_to_use = 2; - - scsi_adjust_queue_depth(device, - (device->tagged_supported ? - MSG_SIMPLE_TAG : 0), - depth_to_use); - - return 0; -} - -/* Detect all FC Arbitrated Loops attached to the machine. - fc4 module has done all the work for us... */ -int __init fcal_detect(struct scsi_host_template *tpnt) -{ - int nfcals = 0; - fc_channel *fc; - int fcalcount; - int i; - - tpnt->proc_name = "fcal"; - fcalcount = 0; - for_each_online_fc_channel(fc) - if (fc->posmap) - fcalcount++; - FCALND(("%d channels online\n", fcalcount)) - if (!fcalcount) { -#if defined(MODULE) && defined(CONFIG_FC4_SOCAL_MODULE) && defined(CONFIG_KMOD) - request_module("socal"); - - for_each_online_fc_channel(fc) - if (fc->posmap) - fcalcount++; - if (!fcalcount) -#endif - return 0; - } - for_each_online_fc_channel(fc) { - struct Scsi_Host *host; - long *ages; - struct fcal *fcal; - - if (!fc->posmap) continue; - - /* Strange, this is already registered to some other SCSI host, then it cannot be fcal */ - if (fc->scsi_name[0]) continue; - memcpy (fc->scsi_name, "FCAL", 4); - - fc->can_queue = FCAL_CAN_QUEUE; - fc->rsp_size = 64; - fc->encode_addr = fcal_encode_addr; - - ages = kmalloc (128 * sizeof(long), GFP_KERNEL); - if (!ages) continue; - - host = scsi_register (tpnt, sizeof (struct fcal)); - if (!host) - { - kfree(ages); - continue; - } - - if (!try_module_get(fc->module)) { - kfree(ages); - scsi_unregister(host); - continue; - } - - nfcals++; - - fcal = (struct fcal *)host->hostdata; - - fc->fcp_register(fc, TYPE_SCSI_FCP, 0); - - for (i = 0; i < fc->posmap->len; i++) { - int status, target, alpa; - - alpa = fc->posmap->list[i]; - FCALD(("Sending PLOGI to %02x\n", alpa)) - target = alpa2target[alpa]; - status = fc_do_plogi(fc, alpa, fcal->node_wwn + target, - fcal->nport_wwn + target); - FCALD(("PLOGI returned with status %d\n", status)) - if (status != FC_STATUS_OK) - continue; - FCALD(("Sending PRLI to %02x\n", alpa)) - status = fc_do_prli(fc, alpa); - FCALD(("PRLI returned with status %d\n", status)) - if (status == FC_STATUS_OK) - fcal->map[target] = 1; - } - - host->max_id = 127; - host->irq = fc->irq; -#ifdef __sparc_v9__ - host->unchecked_isa_dma = 1; -#endif - - fc->channels = 1; - fc->targets = 127; - fc->ages = ages; - memset (ages, 0, 128 * sizeof(long)); - - fcal->fc = fc; - - FCALD(("Found FCAL\n")) - } - if (nfcals) -#ifdef __sparc__ - printk ("FCAL: Total of %d Sun Enterprise Network Array (A5000 or EX500) channels found\n", nfcals); -#else - printk ("FCAL: Total of %d Fibre Channel Arbitrated Loops found\n", nfcals); -#endif - return nfcals; -} - -int fcal_release(struct Scsi_Host *host) -{ - struct fcal *fcal = (struct fcal *)host->hostdata; - fc_channel *fc = fcal->fc; - - module_put(fc->module); - - fc->fcp_register(fc, TYPE_SCSI_FCP, 1); - FCALND((" releasing fcal.\n")); - kfree (fc->ages); - FCALND(("released fcal!\n")); - return 0; -} - -#undef SPRINTF -#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); } - -int fcal_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout) -{ - struct fcal *fcal; - fc_channel *fc; - char *pos = buffer; - int i, j; - - if (inout) return length; - - fcal = (struct fcal *)host->hostdata; - fc = fcal->fc; - -#ifdef __sparc__ - SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s PROM node %x\n", fc->name, fc->dev->prom_node); -#else - SPRINTF ("Fibre Channel Arbitrated Loop on %s\n", fc->name); -#endif - SPRINTF ("Initiator AL-PA: %02x\n", fc->sid); - - SPRINTF ("\nAttached devices:\n"); - - for (i = 0; i < fc->posmap->len; i++) { - unsigned char alpa = fc->posmap->list[i]; - unsigned char target; - u32 *u1, *u2; - - target = alpa2target[alpa]; - u1 = (u32 *)&fcal->nport_wwn[target]; - u2 = (u32 *)&fcal->node_wwn[target]; - if (!u1[0] && !u1[1]) { - SPRINTF (" [AL-PA: %02x] Not responded to PLOGI\n", alpa); - } else if (!fcal->map[target]) { - SPRINTF (" [AL-PA: %02x, Port WWN: %08x%08x, Node WWN: %08x%08x] Not responded to PRLI\n", - alpa, u1[0], u1[1], u2[0], u2[1]); - } else { - struct scsi_device *scd; - shost_for_each_device(scd, host) - if (scd->id == target) { - SPRINTF (" [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x] ", - alpa, target, u1[0], u1[1], u2[0], u2[1]); - SPRINTF ("%s ", scsi_device_type(scd->type)); - - for (j = 0; (j < 8) && (scd->vendor[j] >= 0x20); j++) - SPRINTF ("%c", scd->vendor[j]); - SPRINTF (" "); - - for (j = 0; (j < 16) && (scd->model[j] >= 0x20); j++) - SPRINTF ("%c", scd->model[j]); - - SPRINTF ("\n"); - } - } - } - SPRINTF ("\n"); - - *start = buffer + offset; - - if ((pos - buffer) < offset) - return 0; - else if (pos - buffer - offset < length) - return pos - buffer - offset; - else - return length; -} - -/* - For FC-AL, we use a simple addressing: we have just one channel 0, - and all AL-PAs are mapped to targets 0..0x7e - */ -static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd) -{ - struct fcal *f; - - /* We don't support LUNs yet - I'm not sure if LUN should be in SCSI fcp_cdb, or in second byte of addr[0] */ - if (SCpnt->cmnd[1] & 0xe0) return -EINVAL; - /* FC-PLDA tells us... */ - memset(addr, 0, 8); - f = (struct fcal *)SCpnt->device->host->hostdata; - if (!f->map[SCpnt->device->id]) - return -EINVAL; - /* Now, determine DID: It will be Native Identifier, so we zero upper - 2 bytes of the 3 byte DID, lowest byte will be AL-PA */ - fcmd->did = target2alpa[SCpnt->device->id]; - FCALD(("trying DID %06x\n", fcmd->did)) - return 0; -} - -static struct scsi_host_template driver_template = { - .name = "Fibre Channel Arbitrated Loop", - .detect = fcal_detect, - .release = fcal_release, - .proc_info = fcal_proc_info, - .queuecommand = fcp_scsi_queuecommand, - .slave_configure = fcal_slave_configure, - .can_queue = FCAL_CAN_QUEUE, - .this_id = -1, - .sg_tablesize = 1, - .cmd_per_lun = 1, - .use_clustering = ENABLE_CLUSTERING, - .eh_abort_handler = fcp_scsi_abort, - .eh_device_reset_handler = fcp_scsi_dev_reset, - .eh_host_reset_handler = fcp_scsi_host_reset, -}; -#include "scsi_module.c" - -MODULE_LICENSE("GPL"); - diff --git a/drivers/scsi/fcal.h b/drivers/scsi/fcal.h deleted file mode 100644 index 7ff2c349..0000000 --- a/drivers/scsi/fcal.h +++ /dev/null @@ -1,27 +0,0 @@ -/* fcal.h: Generic Fibre Channel Arbitrated Loop SCSI host adapter driver definitions. - * - * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#ifndef _FCAL_H -#define _FCAL_H - -#include "../fc4/fcp_impl.h" - -struct fcal { - /* fc must be first */ - fc_channel *fc; - unsigned char map[128]; - fc_wwn nport_wwn[128]; - fc_wwn node_wwn[128]; -}; - -/* Arbitrary constant. Cannot be too large, as fc4 layer has limitations - for a particular channel */ -#define FCAL_CAN_QUEUE 512 - -int fcal_detect(struct scsi_host_template *); -int fcal_release(struct Scsi_Host *); -int fcal_slave_configure(struct scsi_device *); - -#endif /* !(_FCAL_H) */ diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c deleted file mode 100644 index 0363c1c..0000000 --- a/drivers/scsi/pluto.c +++ /dev/null @@ -1,349 +0,0 @@ -/* pluto.c: SparcSTORAGE Array SCSI host adapter driver. - * - * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_KMOD -#include -#endif - -#include - -#include "scsi.h" -#include -#include "../fc4/fcp_impl.h" -#include "pluto.h" - -#include - -#define RQ_SCSI_BUSY 0xffff -#define RQ_SCSI_DONE 0xfffe - -/* #define PLUTO_DEBUG */ - -#define pluto_printk printk ("PLUTO %s: ", fc->name); printk - -#ifdef PLUTO_DEBUG -#define PLD(x) pluto_printk x; -#define PLND(x) printk ("PLUTO: "); printk x; -#else -#define PLD(x) -#define PLND(x) -#endif - -static struct ctrl_inquiry { - struct Scsi_Host host; - struct pluto pluto; - Scsi_Cmnd cmd; - char inquiry[256]; - fc_channel *fc; -} *fcs __initdata; -static int fcscount __initdata = 0; -static atomic_t fcss __initdata = ATOMIC_INIT(0); -static DECLARE_COMPLETION(fc_detect_complete); - -static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd); - -static void __init pluto_detect_done(Scsi_Cmnd *SCpnt) -{ - /* Do nothing */ -} - -static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt) -{ - PLND(("Detect done %08lx\n", (long)SCpnt)) - if (atomic_dec_and_test (&fcss)) - complete(&fc_detect_complete); -} - -int pluto_slave_configure(struct scsi_device *device) -{ - int depth_to_use; - - if (device->tagged_supported) - depth_to_use = /* 254 */ 8; - else - depth_to_use = 2; - - scsi_adjust_queue_depth(device, - (device->tagged_supported ? - MSG_SIMPLE_TAG : 0), - depth_to_use); - - return 0; -} - -/* Detect all SSAs attached to the machine. - To be fast, do it on all online FC channels at the same time. */ -int __init pluto_detect(struct scsi_host_template *tpnt) -{ - int i, retry, nplutos; - fc_channel *fc; - struct scsi_device dev; - - tpnt->proc_name = "pluto"; - fcscount = 0; - for_each_online_fc_channel(fc) { - if (!fc->posmap) - fcscount++; - } - PLND(("%d channels online\n", fcscount)) - if (!fcscount) { -#if defined(MODULE) && defined(CONFIG_FC4_SOC_MODULE) && defined(CONFIG_KMOD) - request_module("soc"); - - for_each_online_fc_channel(fc) { - if (!fc->posmap) - fcscount++; - } - if (!fcscount) -#endif - return 0; - } - fcs = kcalloc(fcscount, sizeof (struct ctrl_inquiry), GFP_DMA); - if (!fcs) { - printk ("PLUTO: Not enough memory to probe\n"); - return 0; - } - - memset (&dev, 0, sizeof(dev)); - atomic_set (&fcss, fcscount); - - i = 0; - for_each_online_fc_channel(fc) { - Scsi_Cmnd *SCpnt; - struct Scsi_Host *host; - struct pluto *pluto; - - if (i == fcscount) break; - if (fc->posmap) continue; - - PLD(("trying to find SSA\n")) - - /* If this is already registered to some other SCSI host, then it cannot be pluto */ - if (fc->scsi_name[0]) continue; - memcpy (fc->scsi_name, "SSA", 4); - - fcs[i].fc = fc; - - fc->can_queue = PLUTO_CAN_QUEUE; - fc->rsp_size = 64; - fc->encode_addr = pluto_encode_addr; - - fc->fcp_register(fc, TYPE_SCSI_FCP, 0); - - SCpnt = &(fcs[i].cmd); - host = &(fcs[i].host); - pluto = (struct pluto *)host->hostdata; - - pluto->fc = fc; - - SCpnt->cmnd[0] = INQUIRY; - SCpnt->cmnd[4] = 255; - - /* FC layer requires this, so that SCpnt->device->tagged_supported is initially 0 */ - SCpnt->device = &dev; - dev.host = host; - - SCpnt->cmd_len = COMMAND_SIZE(INQUIRY); - - SCpnt->request->cmd_flags &= ~REQ_STARTED; - - SCpnt->request_bufflen = 256; - SCpnt->request_buffer = fcs[i].inquiry; - PLD(("set up %d %08lx\n", i, (long)SCpnt)) - i++; - } - - for (retry = 0; retry < 5; retry++) { - for (i = 0; i < fcscount; i++) { - if (!fcs[i].fc) break; - if (!(fcs[i].cmd.request->cmd_flags & REQ_STARTED)) { - fcs[i].cmd.request->cmd_flags |= REQ_STARTED; - disable_irq(fcs[i].fc->irq); - PLND(("queuecommand %d %d\n", retry, i)) - fcp_scsi_queuecommand (&(fcs[i].cmd), - pluto_detect_scsi_done); - enable_irq(fcs[i].fc->irq); - } - } - - wait_for_completion_timeout(&fc_detect_complete, 10 * HZ); - PLND(("Woken up\n")) - if (!atomic_read(&fcss)) - break; /* All fc channels have answered us */ - } - - PLND(("Finished search\n")) - for (i = 0, nplutos = 0; i < fcscount; i++) { - Scsi_Cmnd *SCpnt; - - if (!(fc = fcs[i].fc)) break; - - SCpnt = &(fcs[i].cmd); - - /* Let FC mid-level free allocated resources */ - pluto_detect_scsi_done(SCpnt); - - if (!SCpnt->result) { - struct pluto_inquiry *inq; - struct pluto *pluto; - struct Scsi_Host *host; - - inq = (struct pluto_inquiry *)fcs[i].inquiry; - - if ((inq->dtype & 0x1f) == TYPE_PROCESSOR && - !strncmp (inq->vendor_id, "SUN", 3) && - !strncmp (inq->product_id, "SSA", 3)) { - char *p; - long *ages; - - ages = kcalloc((inq->channels + 1) * inq->targets, sizeof(long), GFP_KERNEL); - if (!ages) continue; - - host = scsi_register (tpnt, sizeof (struct pluto)); - if(!host) - { - kfree(ages); - continue; - } - - if (!try_module_get(fc->module)) { - kfree(ages); - scsi_unregister(host); - continue; - } - - nplutos++; - - pluto = (struct pluto *)host->hostdata; - - host->max_id = inq->targets; - host->max_channel = inq->channels; - host->irq = fc->irq; - - fc->channels = inq->channels + 1; - fc->targets = inq->targets; - fc->ages = ages; - - pluto->fc = fc; - memcpy (pluto->rev_str, inq->revision, 4); - pluto->rev_str[4] = 0; - p = strchr (pluto->rev_str, ' '); - if (p) *p = 0; - memcpy (pluto->fw_rev_str, inq->fw_revision, 4); - pluto->fw_rev_str[4] = 0; - p = strchr (pluto->fw_rev_str, ' '); - if (p) *p = 0; - memcpy (pluto->serial_str, inq->serial, 12); - pluto->serial_str[12] = 0; - p = strchr (pluto->serial_str, ' '); - if (p) *p = 0; - - PLD(("Found SSA rev %s fw rev %s serial %s %dx%d\n", pluto->rev_str, pluto->fw_rev_str, pluto->serial_str, host->max_channel, host->max_id)) - } else - fc->fcp_register(fc, TYPE_SCSI_FCP, 1); - } else - fc->fcp_register(fc, TYPE_SCSI_FCP, 1); - } - kfree(fcs); - if (nplutos) - printk ("PLUTO: Total of %d SparcSTORAGE Arrays found\n", nplutos); - return nplutos; -} - -int pluto_release(struct Scsi_Host *host) -{ - struct pluto *pluto = (struct pluto *)host->hostdata; - fc_channel *fc = pluto->fc; - - module_put(fc->module); - - fc->fcp_register(fc, TYPE_SCSI_FCP, 1); - PLND((" releasing pluto.\n")); - kfree (fc->ages); - PLND(("released pluto!\n")); - return 0; -} - -const char *pluto_info(struct Scsi_Host *host) -{ - static char buf[128], *p; - struct pluto *pluto = (struct pluto *) host->hostdata; - - sprintf(buf, "SUN SparcSTORAGE Array %s fw %s serial %s %dx%d on %s", - pluto->rev_str, pluto->fw_rev_str, pluto->serial_str, - host->max_channel, host->max_id, pluto->fc->name); -#ifdef __sparc__ - p = strchr(buf, 0); - sprintf(p, " PROM node %x", pluto->fc->dev->prom_node); -#endif - return buf; -} - -/* SSA uses this FC4S addressing: - switch (addr[0]) - { - case 0: CONTROLLER - All of addr[1]..addr[3] has to be 0 - case 1: SINGLE DISK - addr[1] channel, addr[2] id, addr[3] 0 - case 2: DISK GROUP - ??? - } - - So that SCSI mid-layer can access to these, we reserve - channel 0 id 0 lun 0 for CONTROLLER - and channels 1 .. max_channel are normal single disks. - */ -static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd) -{ - PLND(("encode addr %d %d %d\n", SCpnt->device->channel, SCpnt->device->id, SCpnt->cmnd[1] & 0xe0)) - /* We don't support LUNs - neither does SSA :) */ - if (SCpnt->cmnd[1] & 0xe0) - return -EINVAL; - if (!SCpnt->device->channel) { - if (SCpnt->device->id) - return -EINVAL; - memset (addr, 0, 4 * sizeof(u16)); - } else { - addr[0] = 1; - addr[1] = SCpnt->device->channel - 1; - addr[2] = SCpnt->device->id; - addr[3] = 0; - } - /* We're Point-to-Point, so target it to the default DID */ - fcmd->did = fc->did; - PLND(("trying %04x%04x%04x%04x\n", addr[0], addr[1], addr[2], addr[3])) - return 0; -} - -static struct scsi_host_template driver_template = { - .name = "Sparc Storage Array 100/200", - .detect = pluto_detect, - .release = pluto_release, - .info = pluto_info, - .queuecommand = fcp_scsi_queuecommand, - .slave_configure = pluto_slave_configure, - .can_queue = PLUTO_CAN_QUEUE, - .this_id = -1, - .sg_tablesize = 1, - .cmd_per_lun = 1, - .use_clustering = ENABLE_CLUSTERING, - .eh_abort_handler = fcp_scsi_abort, - .eh_device_reset_handler = fcp_scsi_dev_reset, - .eh_host_reset_handler = fcp_scsi_host_reset, -}; - -#include "scsi_module.c" - -MODULE_LICENSE("GPL"); - diff --git a/drivers/scsi/pluto.h b/drivers/scsi/pluto.h deleted file mode 100644 index 5da2061..0000000 --- a/drivers/scsi/pluto.h +++ /dev/null @@ -1,47 +0,0 @@ -/* pluto.h: SparcSTORAGE Array SCSI host adapter driver definitions. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#ifndef _PLUTO_H -#define _PLUTO_H - -#include "../fc4/fcp_impl.h" - -struct pluto { - /* This must be first */ - fc_channel *fc; - char rev_str[5]; - char fw_rev_str[5]; - char serial_str[13]; -}; - -struct pluto_inquiry { - u8 dtype; - u8 removable:1, qualifier:7; - u8 iso:2, ecma:3, ansi:3; - u8 aenc:1, trmiop:1, :2, rdf:4; - u8 len; - u8 xxx1; - u8 xxx2; - u8 reladdr:1, wbus32:1, wbus16:1, sync:1, linked:1, :1, cmdque:1, softreset:1; - u8 vendor_id[8]; - u8 product_id[16]; - u8 revision[4]; - u8 fw_revision[4]; - u8 serial[12]; - u8 xxx3[2]; - u8 channels; - u8 targets; -}; - -/* This is the max number of outstanding SCSI commands per pluto */ -#define PLUTO_CAN_QUEUE 254 - -int pluto_detect(struct scsi_host_template *); -int pluto_release(struct Scsi_Host *); -const char * pluto_info(struct Scsi_Host *); -int pluto_slave_configure(struct scsi_device *); - -#endif /* !(_PLUTO_H) */ - -- cgit v0.10.2 From 645a0c6c48e0122f4212e3957e73bddc18788d99 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 15 Oct 2007 21:07:17 -0400 Subject: [SCSI] include linux/scatterlist.h in scsi_eh.h Spotted by Paul Jackson The error handler rework moved the scatterlist into a globally exposed structure in scsi_eh.h; unfortunately, the scatterlist include needs to move from scsi_error.c to scsi_eh.h to allow this to compile universally. Acked-by: Paul Jackson Signed-off-by: James Bottomley diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index d29f846..ebaca4c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 44224ba..d21b891 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -1,6 +1,8 @@ #ifndef _SCSI_SCSI_EH_H #define _SCSI_SCSI_EH_H +#include + #include struct scsi_device; struct Scsi_Host; -- cgit v0.10.2 From 7a39ac3f25bef018862a991d754aff681c019127 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 25 Sep 2007 22:45:53 -0500 Subject: [SCSI] make supported_mode default to initiator. if shost->supported mode is zero (i.e. MODE_UNKNOWN) show it as initiator (it's obviously an unconverted driver that won't do target). Acked-by: FUJITA Tomonori Signed-off-by: James Bottomley diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 112ab6a..24271a8 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -345,6 +345,12 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->active_mode = sht->supported_mode; shost->use_sg_chaining = sht->use_sg_chaining; + if (sht->supported_mode == MODE_UNKNOWN) + /* means we didn't set it ... default to INITIATOR */ + shost->active_mode = MODE_INITIATOR; + else + shost->active_mode = sht->supported_mode; + if (sht->max_host_blocked) shost->max_host_blocked = sht->max_host_blocked; else diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index daed37d..d531cee 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -209,11 +209,13 @@ show_shost_mode(unsigned int mode, char *buf) static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); + unsigned int supported_mode = shost->hostt->supported_mode; - if (shost->hostt->supported_mode == MODE_UNKNOWN) - return snprintf(buf, 20, "unknown\n"); - else - return show_shost_mode(shost->hostt->supported_mode, buf); + if (supported_mode == MODE_UNKNOWN) + /* by default this should be initiator */ + supported_mode = MODE_INITIATOR; + + return show_shost_mode(supported_mode, buf); } static CLASS_DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL); -- cgit v0.10.2 From 0fec02c93f60fb44ba3a24a0d3e4a52521d34d3f Mon Sep 17 00:00:00 2001 From: HighPoint Linux Team Date: Mon, 15 Oct 2007 14:42:52 +0800 Subject: [SCSI] hptiop: avoid buffer overflow when returning sense data The newer firmware may return more than 96 bytes of sense data when it does autosense. Truncate this to the size of the SCSI layer sense buffer to avoid an overrun. Signed-off-by: HighPoint Linux Team Signed-off-by: James Bottomley diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 8515054..0844331 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -375,8 +375,9 @@ static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) scp->result = SAM_STAT_CHECK_CONDITION; memset(&scp->sense_buffer, 0, sizeof(scp->sense_buffer)); - memcpy(&scp->sense_buffer, - &req->sg_list, le32_to_cpu(req->dataxfer_length)); + memcpy(&scp->sense_buffer, &req->sg_list, + min(sizeof(scp->sense_buffer), + le32_to_cpu(req->dataxfer_length))); break; default: -- cgit v0.10.2 From e9e42faf47255274a1ed0b9bf1c46118023ec5fa Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 15 Oct 2007 20:51:32 +0100 Subject: [SCSI] initio: Fix merge fallout Fix IRQ reporting - just assign the ->pci_dev pointer earlier and use the pci_dev irq field rather than keeping a private one Init the spinlock as it works better on SMP that way Signed-off-by: Alan Cox Signed-off-by: James Bottomley diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 22d40fd..4c4465d 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -665,7 +665,7 @@ static void initio_init(struct initio_host * host, u8 *bios_addr) host->max_tags[i] = 0xFF; } /* for */ printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n", - host->addr, host->irq, + host->addr, host->pci_dev->irq, host->bios_addr, host->scsi_id); /* Reset SCSI Bus */ if (host->config & HCC_SCSI_RESET) { @@ -2891,6 +2891,8 @@ static int initio_probe_one(struct pci_dev *pdev, goto out_release_region; } + host->pci_dev = pdev; + host->num_scbs = num_scb; host->scb = scb; host->next_pending = scb; @@ -2905,6 +2907,7 @@ static int initio_probe_one(struct pci_dev *pdev, host->scb_end = tmp; host->first_avail = scb; host->last_avail = prev; + spin_lock_init(&host->avail_lock); initio_init(host, phys_to_virt(bios_seg << 4)); @@ -2928,7 +2931,6 @@ static int initio_probe_one(struct pci_dev *pdev, } pci_set_drvdata(pdev, shost); - host->pci_dev = pdev; error = scsi_add_host(shost, &pdev->dev); if (error) -- cgit v0.10.2 From ff86ba59fbf6f0fd56b367b99b66dc8fb8ad61e7 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 18 Oct 2007 12:52:37 +0200 Subject: [SCSI] lpfc: lpfc_debugfs.c: fix typo This patch fixes a typo introduced by commit bbfbbbc1182f8b44c8cc4c99f4a3f3a512149022. It wasn't a compile error since CONFIG_LPFC_DEBUG_FS is not (yet?) available as an option. Signed-off-by: Adrian Bunk Signed-off-by: James Bottomley diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 149fdd2..d6a98bc 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -901,7 +901,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) } } - vport->disc_trc = kmzlloc( + vport->disc_trc = kzalloc( (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc), GFP_KERNEL); -- cgit v0.10.2 From 875baf3cbc0f11009ef5ca33c78210d265c8d779 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 16 Oct 2007 14:28:20 -0700 Subject: [SCSI] qla2xxx: printk fixes drivers/scsi/qla2xxx/qla_sup.c: In function 'qla24xx_write_flash_data': drivers/scsi/qla2xxx/qla_sup.c:655: warning: format '%llx' expects type 'long long unsigned int', but argument 6 has type 'dma_addr_t' drivers/scsi/qla2xxx/qla_sup.c: In function 'qla25xx_read_optrom_data': drivers/scsi/qla2xxx/qla_sup.c:1853: warning: format '%llx' expects type 'long long unsigned int', but argument 6 has type 'dma_addr_t' Signed-off-by: Andrew Morton Acked-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 40b059f..6670ad5 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -656,7 +656,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, "Unable to burst-write optrom segment " "(%x/%x/%llx).\n", ret, flash_data_to_access_addr(faddr), - optrom_dma); + (unsigned long long)optrom_dma); qla_printk(KERN_WARNING, ha, "Reverting to slow-write.\n"); @@ -1853,7 +1853,8 @@ qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, qla_printk(KERN_WARNING, ha, "Unable to burst-read optrom segment " "(%x/%x/%llx).\n", rval, - flash_data_to_access_addr(faddr), optrom_dma); + flash_data_to_access_addr(faddr), + (unsigned long long)optrom_dma); qla_printk(KERN_WARNING, ha, "Reverting to slow-read.\n"); -- cgit v0.10.2 From 4135f9d28af912d541c0c32f1bc2ee6da23306eb Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 18 Oct 2007 12:52:07 +0200 Subject: [SCSI] aic7xxx_old: fix accidental logic reversal Commit bbfbbbc1182f8b44c8cc4c99f4a3f3a512149022 accidentally reversed the logic of this NULL check. Spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: James Bottomley diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 4025608..8f8db5f 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -8417,7 +8417,7 @@ aic7xxx_alloc(struct scsi_host_template *sht, struct aic7xxx_host *temp) p->host = host; p->scb_data = kzalloc(sizeof(scb_data_type), GFP_ATOMIC); - if (!p->scb_data) + if (p->scb_data) { scbq_init (&p->scb_data->free_scbs); } -- cgit v0.10.2 From 05dd7ed2c7e22d0fc3027fc27a072664bbdf8274 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 18 Oct 2007 12:51:05 +0200 Subject: [SCSI] gdth: __init fixes This patch fixes the following build warnings: WARNING: vmlinux.o(.text+0xbcffdb): Section mismatch: reference to .init.text.20:gdth_search_drives (between 'gdth_pci_probe_one' and 'gdth_start_timeout') WARNING: vmlinux.o(.text+0xbd0102): Section mismatch: reference to .init.text.20:gdth_enable_int (between 'gdth_pci_probe_one' and 'gdth_start_timeout') Signed-off-by: Adrian Bunk Signed-off-by: James Bottomley diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 3ac080e..56de5a6 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4734,7 +4734,7 @@ static struct scsi_host_template gdth_template = { }; #ifdef CONFIG_ISA -static int gdth_isa_probe_one(ulong32 isa_bios) +static int __init gdth_isa_probe_one(ulong32 isa_bios) { struct Scsi_Host *shp; gdth_ha_str *ha; @@ -4862,7 +4862,7 @@ static int gdth_isa_probe_one(ulong32 isa_bios) #endif /* CONFIG_ISA */ #ifdef CONFIG_EISA -static int gdth_eisa_probe_one(ushort eisa_slot) +static int __init gdth_eisa_probe_one(ushort eisa_slot) { struct Scsi_Host *shp; gdth_ha_str *ha; @@ -4991,7 +4991,7 @@ static int gdth_eisa_probe_one(ushort eisa_slot) #endif /* CONFIG_EISA */ #ifdef CONFIG_PCI -static int gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr) +static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr) { struct Scsi_Host *shp; gdth_ha_str *ha; -- cgit v0.10.2 From eb7a1698d24783dd215cb86a12cadebe9b4e7046 Mon Sep 17 00:00:00 2001 From: Johannes Dickgreber Date: Wed, 3 Oct 2007 13:22:19 +0200 Subject: [SCSI] qla1280: uses wrong failure path after failed pci_set_dma_mask A failure here wouldn't currently free the irq; go to the irq free path instead. Signed-off-by: Johannes Dickgreber Acked-by: Jes Sorensen Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 76089cf..3aeb68b 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -4310,7 +4310,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) printk(KERN_WARNING "scsi(%li): Unable to set a " "suitable DMA mask - aborting\n", ha->host_no); error = -ENODEV; - goto error_free_irq; + goto error_put_host; } } else dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n", @@ -4320,7 +4320,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) printk(KERN_WARNING "scsi(%li): Unable to set a " "suitable DMA mask - aborting\n", ha->host_no); error = -ENODEV; - goto error_free_irq; + goto error_put_host; } #endif -- cgit v0.10.2 From b5720729f58a4a05b0e2c8c61ac3ed3a3e9f94e5 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 19 Oct 2007 10:32:21 +0200 Subject: [SCSI] aic7xxx: Add suspend/resume support The aic7xxx driver already contains fragments for suspend/resume support. So we only need to update them to the current interface and have full PCI suspend/resume. Signed-off-by: Hannes Reinecke Tested-by: Jens Axboe Signed-off-by: James Bottomley diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c index c4d1723..6d86a9b 100644 --- a/drivers/scsi/aic7xxx/aic7770.c +++ b/drivers/scsi/aic7xxx/aic7770.c @@ -60,8 +60,6 @@ #define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */ static int aic7770_chip_init(struct ahc_softc *ahc); -static int aic7770_suspend(struct ahc_softc *ahc); -static int aic7770_resume(struct ahc_softc *ahc); static int aha2840_load_seeprom(struct ahc_softc *ahc); static ahc_device_setup_t ahc_aic7770_VL_setup; static ahc_device_setup_t ahc_aic7770_EISA_setup; @@ -155,8 +153,6 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) return (error); ahc->bus_chip_init = aic7770_chip_init; - ahc->bus_suspend = aic7770_suspend; - ahc->bus_resume = aic7770_resume; error = ahc_reset(ahc, /*reinit*/FALSE); if (error != 0) @@ -272,18 +268,6 @@ aic7770_chip_init(struct ahc_softc *ahc) return (ahc_chip_init(ahc)); } -static int -aic7770_suspend(struct ahc_softc *ahc) -{ - return (ahc_suspend(ahc)); -} - -static int -aic7770_resume(struct ahc_softc *ahc) -{ - return (ahc_resume(ahc)); -} - /* * Read the 284x SEEPROM. */ diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 27adbb2..ce638aa 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -1003,8 +1003,15 @@ struct ahd_suspend_channel_state { uint8_t seqctl; }; +struct ahd_suspend_pci_state { + uint32_t devconfig; + uint8_t command; + uint8_t csize_lattime; +}; + struct ahd_suspend_state { struct ahd_suspend_channel_state channel[2]; + struct ahd_suspend_pci_state pci_state; uint8_t optionmode; uint8_t dscommand0; uint8_t dspcistatus; @@ -1333,6 +1340,8 @@ struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t); int ahd_pci_config(struct ahd_softc *, struct ahd_pci_identity *); int ahd_pci_test_register_access(struct ahd_softc *); +void ahd_pci_suspend(struct ahd_softc *); +void ahd_pci_resume(struct ahd_softc *); /************************** SCB and SCB queue management **********************/ void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, @@ -1343,6 +1352,8 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name); int ahd_softc_init(struct ahd_softc *); void ahd_controller_info(struct ahd_softc *ahd, char *buf); int ahd_init(struct ahd_softc *ahd); +int ahd_suspend(struct ahd_softc *ahd); +void ahd_resume(struct ahd_softc *ahd); int ahd_default_config(struct ahd_softc *ahd); int ahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd); diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 05f692b..a7dd8cd 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -7175,7 +7175,6 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) ahd->flags &= ~AHD_ALL_INTERRUPTS; } -#if 0 int ahd_suspend(struct ahd_softc *ahd) { @@ -7189,19 +7188,15 @@ ahd_suspend(struct ahd_softc *ahd) ahd_shutdown(ahd); return (0); } -#endif /* 0 */ -#if 0 -int +void ahd_resume(struct ahd_softc *ahd) { ahd_reset(ahd, /*reinit*/TRUE); ahd_intr_enable(ahd, TRUE); ahd_restart(ahd); - return (0); } -#endif /* 0 */ /************************** Busy Target Table *********************************/ /* diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index c62ce41..66f0259 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -50,6 +50,8 @@ static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, u_long *bus_addr, uint8_t __iomem **maddr); +static int ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg); +static int ahd_linux_pci_dev_resume(struct pci_dev *pdev); static void ahd_linux_pci_dev_remove(struct pci_dev *pdev); /* Define the macro locally since it's different for different class of chips. @@ -86,10 +88,58 @@ MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); static struct pci_driver aic79xx_pci_driver = { .name = "aic79xx", .probe = ahd_linux_pci_dev_probe, +#ifdef CONFIG_PM + .suspend = ahd_linux_pci_dev_suspend, + .resume = ahd_linux_pci_dev_resume, +#endif .remove = ahd_linux_pci_dev_remove, .id_table = ahd_linux_pci_id_table }; +static int +ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ahd_softc *ahd = pci_get_drvdata(pdev); + int rc; + + if ((rc = ahd_suspend(ahd))) + return rc; + + ahd_pci_suspend(ahd); + + pci_save_state(pdev); + pci_disable_device(pdev); + + if (mesg.event == PM_EVENT_SUSPEND) + pci_set_power_state(pdev, PCI_D3hot); + + return rc; +} + +static int +ahd_linux_pci_dev_resume(struct pci_dev *pdev) +{ + struct ahd_softc *ahd = pci_get_drvdata(pdev); + int rc; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if ((rc = pci_enable_device(pdev))) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to enable device after resume (%d)\n", rc); + return rc; + } + + pci_set_master(pdev); + + ahd_pci_resume(ahd); + + ahd_resume(ahd); + + return rc; +} + static void ahd_linux_pci_dev_remove(struct pci_dev *pdev) { diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 0bada00..7a203a9 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -389,6 +389,33 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) return error; } +void +ahd_pci_suspend(struct ahd_softc *ahd) +{ + /* + * Save chip register configuration data for chip resets + * that occur during runtime and resume events. + */ + ahd->suspend_state.pci_state.devconfig = + ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); + ahd->suspend_state.pci_state.command = + ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1); + ahd->suspend_state.pci_state.csize_lattime = + ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1); + +} + +void +ahd_pci_resume(struct ahd_softc *ahd) +{ + ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, + ahd->suspend_state.pci_state.devconfig, /*bytes*/4); + ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, + ahd->suspend_state.pci_state.command, /*bytes*/1); + ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME, + ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1); +} + /* * Perform some simple tests that should catch situations where * our registers are invalidly mapped. diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index e1bd57b..3d4e42d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -962,16 +962,6 @@ struct ahc_softc { ahc_bus_chip_init_t bus_chip_init; /* - * Bus specific suspend routine. - */ - ahc_bus_suspend_t bus_suspend; - - /* - * Bus specific resume routine. - */ - ahc_bus_resume_t bus_resume; - - /* * Target mode related state kept on a per enabled lun basis. * Targets that are not enabled will have null entries. * As an initiator, we keep one target entry for our initiator @@ -1153,6 +1143,7 @@ struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t); int ahc_pci_config(struct ahc_softc *, struct ahc_pci_identity *); int ahc_pci_test_register_access(struct ahc_softc *); +void ahc_pci_resume(struct ahc_softc *ahc); /*************************** EISA/VL Front End ********************************/ struct aic7770_identity *aic7770_find_device(uint32_t); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index ea5687d..4488946 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -49,6 +49,8 @@ static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, u_long *bus_addr, uint8_t __iomem **maddr); +static int ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg); +static int ahc_linux_pci_dev_resume(struct pci_dev *pdev); static void ahc_linux_pci_dev_remove(struct pci_dev *pdev); /* Define the macro locally since it's different for different class of chips. @@ -133,10 +135,54 @@ MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); static struct pci_driver aic7xxx_pci_driver = { .name = "aic7xxx", .probe = ahc_linux_pci_dev_probe, +#ifdef CONFIG_PM + .suspend = ahc_linux_pci_dev_suspend, + .resume = ahc_linux_pci_dev_resume, +#endif .remove = ahc_linux_pci_dev_remove, .id_table = ahc_linux_pci_id_table }; +static int +ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ahc_softc *ahc = pci_get_drvdata(pdev); + int rc; + + if ((rc = ahc_suspend(ahc))) + return rc; + + pci_save_state(pdev); + pci_disable_device(pdev); + + if (mesg.event == PM_EVENT_SUSPEND) + pci_set_power_state(pdev, PCI_D3hot); + + return rc; +} + +static int +ahc_linux_pci_dev_resume(struct pci_dev *pdev) +{ + struct ahc_softc *ahc = pci_get_drvdata(pdev); + int rc; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if ((rc = pci_enable_device(pdev))) { + dev_printk(KERN_ERR, &pdev->dev, + "failed to enable device after resume (%d)\n", rc); + return rc; + } + + pci_set_master(pdev); + + ahc_pci_resume(ahc); + + return (ahc_resume(ahc)); +} + static void ahc_linux_pci_dev_remove(struct pci_dev *pdev) { diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 09c8172..ae35937 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -633,8 +633,6 @@ static void write_brdctl(struct ahc_softc *ahc, uint8_t value); static uint8_t read_brdctl(struct ahc_softc *ahc); static void ahc_pci_intr(struct ahc_softc *ahc); static int ahc_pci_chip_init(struct ahc_softc *ahc); -static int ahc_pci_suspend(struct ahc_softc *ahc); -static int ahc_pci_resume(struct ahc_softc *ahc); static int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, @@ -791,8 +789,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) ahc->bus_intr = ahc_pci_intr; ahc->bus_chip_init = ahc_pci_chip_init; - ahc->bus_suspend = ahc_pci_suspend; - ahc->bus_resume = ahc_pci_resume; /* Remeber how the card was setup in case there is no SEEPROM */ if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { @@ -2024,18 +2020,9 @@ ahc_pci_chip_init(struct ahc_softc *ahc) return (ahc_chip_init(ahc)); } -static int -ahc_pci_suspend(struct ahc_softc *ahc) -{ - return (ahc_suspend(ahc)); -} - -static int +void ahc_pci_resume(struct ahc_softc *ahc) { - - pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0); - /* * We assume that the OS has restored our register * mappings, etc. Just update the config space registers @@ -2063,7 +2050,6 @@ ahc_pci_resume(struct ahc_softc *ahc) &sxfrctl1); ahc_release_seeprom(&sd); } - return (ahc_resume(ahc)); } static int -- cgit v0.10.2 From 64624d4f46d5e439906bcd3a99a688c833506124 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 19 Oct 2007 10:32:29 +0200 Subject: [SCSI] aic7xxx: Update Maintainer information Might as well take the blame officially. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley diff --git a/MAINTAINERS b/MAINTAINERS index 10deabe..75fd297 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -325,6 +325,12 @@ M: Juergen Fischer L: linux-scsi@vger.kernel.org S: Maintained +AIC7XXX / AIC79XX SCSI DRIVER +P: Hannes Reinecke +M: hare@suse.de +L: linux-scsi@vger.kernel.org +S: Maintained + ALCATEL SPEEDTOUCH USB DRIVER P: Duncan Sands M: duncan.sands@free.fr diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 42c0f14..2d02040 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -315,8 +315,8 @@ uint32_t aic79xx_slowcrc; */ static char *aic79xx = NULL; -MODULE_AUTHOR("Maintainer: Justin T. Gibbs "); -MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); +MODULE_AUTHOR("Maintainer: Hannes Reinecke "); +MODULE_DESCRIPTION("Adaptec AIC790X U320 SCSI Host Bus Adapter driver"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(AIC79XX_DRIVER_VERSION); module_param(aic79xx, charp, 0444); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 7770bef..390b0fc 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -335,8 +335,8 @@ static uint32_t aic7xxx_periodic_otag; */ static char *aic7xxx = NULL; -MODULE_AUTHOR("Maintainer: Justin T. Gibbs "); -MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver"); +MODULE_AUTHOR("Maintainer: Hannes Reinecke "); +MODULE_DESCRIPTION("Adaptec AIC77XX/78XX SCSI Host Bus Adapter driver"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(AIC7XXX_DRIVER_VERSION); module_param(aic7xxx, charp, 0444); -- cgit v0.10.2 From fc2adcfd37f6f1c32d246b5b43f83e38233358ae Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 19 Oct 2007 10:32:34 +0200 Subject: [SCSI] aic7xxx: Fix firmware build If a prefix is selected for flex, we should be using it everywhere. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l index f06e703..c0457b8 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l @@ -66,6 +66,7 @@ static char string_buf[MAX_STR_CONST]; static char *string_buf_ptr; static int parren_count; static char buf[255]; +int mmlineno; %} WORD [A-Za-z_][-A-Za-z_0-9]* @@ -76,7 +77,7 @@ MCARG [^(), \t]+ %% \n { - ++yylineno; + ++mmlineno; } \r ; {SPACE} ; -- cgit v0.10.2 From 20d2d3afa87781fe2674ce17bfb16af08a436e81 Mon Sep 17 00:00:00 2001 From: Johannes Dickgreber Date: Thu, 20 Sep 2007 01:07:50 +0200 Subject: [SCSI] qla1280: eliminate wasted space in request and response ring i think there is wasted space in allocated pages for request and response rings. The allocations are made with REQUEST_ENTRY_CNT + 1 and RESPONSE_ENTRY_CNT + 1, but they are set with 256 and 16. So we got more pages, which we dont use very much so eliminate them. Signed-off-by: Johannes Dickgreber Acked-by: Jes Sorensen Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h index 59915fb..ff2c363 100644 --- a/drivers/scsi/qla1280.h +++ b/drivers/scsi/qla1280.h @@ -91,8 +91,8 @@ #define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS + 2) /* ISP request and response entry counts (37-65535) */ -#define REQUEST_ENTRY_CNT 256 /* Number of request entries. */ -#define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */ +#define REQUEST_ENTRY_CNT 255 /* Number of request entries. */ +#define RESPONSE_ENTRY_CNT 63 /* Number of response entries. */ /* * SCSI Request Block structure (sp) that is placed -- cgit v0.10.2 From 34996acc5571e64be7f3dba3adced1f7221a8d07 Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Fri, 5 Oct 2007 15:54:58 -0400 Subject: [SCSI] sym53c8xx: Work around 53c896 erratum Prevent DMA transfers from crossing the 16MB limit for early 53c896 chips. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index db03c4c..4416939 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1531,6 +1531,10 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, BUG_ON(sym2_transport_template == NULL); instance->transportt = sym2_transport_template; + /* 53c896 rev 1 errata: DMA may not cross 16MB boundary */ + if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && np->revision_id < 2) + instance->dma_boundary = 0xFFFFFF; + spin_unlock_irqrestore(instance->host_lock, flags); return instance; -- cgit v0.10.2 From f363abff55cad0e9c6e73c4eedae13d9ee794880 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:54:59 -0400 Subject: [SCSI] sym53c8xx: Use pci_dev irq number Don't cache a private copy of the interrupt number Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 4416939..e053222 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1288,7 +1288,7 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len) "revision id 0x%x\n", np->s.chip_name, np->device_id, np->revision_id); copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n", - pci_name(np->s.device), IRQ_PRM(np->s.irq)); + pci_name(np->s.device), IRQ_PRM(np->s.device->irq)); copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n", (int) (np->minsync_dt ? np->minsync_dt : np->minsync), np->maxwide ? "Wide" : "Narrow", @@ -1341,8 +1341,8 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev) /* * Free O/S specific resources. */ - if (np->s.irq) - free_irq(np->s.irq, np); + if (pdev->irq) + free_irq(pdev->irq, np); if (np->s.ioaddr) pci_iounmap(pdev, np->s.ioaddr); if (np->s.ramaddr) @@ -1491,7 +1491,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, sym_name(np), pdev->irq); goto attach_failed; } - np->s.irq = pdev->irq; /* * After SCSI devices have been opened, we cannot diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index 0f097ba..bea7bcc 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -184,7 +184,6 @@ struct sym_shcb { void __iomem * ioaddr; /* MMIO kernel io address */ void __iomem * ramaddr; /* RAM kernel io address */ u_short io_ws; /* IO window size */ - int irq; /* IRQ number */ struct timer_list timer; /* Timer handler link header */ u_long lasttime; -- cgit v0.10.2 From 39c05d1e3c85c725e140ded1281bbb2303dfe5d3 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:00 -0400 Subject: [SCSI] sym53c8xx: Remove data_mapping and data_mapped Before all commands used sg, data_mapping and data_mapped were used to distinguish whether the command had used map_single or map_sg. Now all commands are sg, so we can delete data_mapping, data_mapped and the wrapper functions __unmap_scsi_data, __map_scsi_sg_data, unmap_scsi_data and map_scsi_sg_data. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index e053222..cfce00b 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -134,8 +134,6 @@ static struct scsi_transport_template *sym2_transport_template = NULL; * Driver private area in the SCSI command structure. */ struct sym_ucmd { /* Override the SCSI pointer structure */ - dma_addr_t data_mapping; - unsigned char data_mapped; unsigned char to_do; /* For error handling */ void (*old_done)(struct scsi_cmnd *); /* For error handling */ struct completion *eh_done; /* For error handling */ @@ -144,37 +142,12 @@ struct sym_ucmd { /* Override the SCSI pointer structure */ #define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp)) #define SYM_SOFTC_PTR(cmd) sym_get_hcb(cmd->device->host) -static void __unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) -{ - if (SYM_UCMD_PTR(cmd)->data_mapped) - scsi_dma_unmap(cmd); - - SYM_UCMD_PTR(cmd)->data_mapped = 0; -} - -static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) -{ - int use_sg; - - use_sg = scsi_dma_map(cmd); - if (use_sg > 0) { - SYM_UCMD_PTR(cmd)->data_mapped = 2; - SYM_UCMD_PTR(cmd)->data_mapping = use_sg; - } - - return use_sg; -} - -#define unmap_scsi_data(np, cmd) \ - __unmap_scsi_data(np->s.device, cmd) -#define map_scsi_sg_data(np, cmd) \ - __map_scsi_sg_data(np->s.device, cmd) /* * Complete a pending CAM CCB. */ void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *cmd) { - unmap_scsi_data(np, cmd); + scsi_dma_unmap(cmd); cmd->scsi_done(cmd); } @@ -307,14 +280,14 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd cp->data_len = 0; - use_sg = map_scsi_sg_data(np, cmd); + use_sg = scsi_dma_map(cmd); if (use_sg > 0) { struct scatterlist *sg; struct sym_tcb *tp = &np->target[cp->target]; struct sym_tblmove *data; if (use_sg > SYM_CONF_MAX_SG) { - unmap_scsi_data(np, cmd); + scsi_dma_unmap(cmd); return -1; } -- cgit v0.10.2 From 71c222dc45ddf01b0dabb8a4d3e232e13e1452b5 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:01 -0400 Subject: [SCSI] sym53c8xx: Remove unnecessary check in queuecommand The midlayer won't scan the host ID, so we don't need to check. This is the only caller of sym_xpt_done2, so remove that too. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index cfce00b..9fc2ae8 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -151,13 +151,6 @@ void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *cmd) cmd->scsi_done(cmd); } -static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *cmd, int cam_status) -{ - sym_set_cam_status(cmd, cam_status); - sym_xpt_done(np, cmd); -} - - /* * Tell the SCSI layer about a BUS RESET. */ @@ -324,15 +317,6 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd) int order; /* - * Minimal checkings, so that we will not - * go outside our tables. - */ - if (sdev->id == np->myaddr) { - sym_xpt_done2(np, cmd, DID_NO_CONNECT); - return 0; - } - - /* * Retrieve the target descriptor. */ tp = &np->target[sdev->id]; @@ -537,7 +521,7 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd, struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd); int sts = 0; - cmd->scsi_done = done; + cmd->scsi_done = done; memset(ucp, 0, sizeof(*ucp)); /* -- cgit v0.10.2 From 6c9746b363b8191587191518a65d5de93df80a92 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:02 -0400 Subject: [SCSI] sym53c8xx: Don't disable interrupts in the interrupt handler Interrupts can't be re-entered, so it's sufficient to call spin_lock, not spin_lock_irqsave(). Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 9fc2ae8..b5e7c64 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -550,14 +550,13 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd, */ static irqreturn_t sym53c8xx_intr(int irq, void *dev_id) { - unsigned long flags; - struct sym_hcb *np = (struct sym_hcb *)dev_id; + struct sym_hcb *np = dev_id; if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("["); - spin_lock_irqsave(np->s.host->host_lock, flags); + spin_lock(np->s.host->host_lock); sym_interrupt(np); - spin_unlock_irqrestore(np->s.host->host_lock, flags); + spin_unlock(np->s.host->host_lock); if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n"); -- cgit v0.10.2 From 2ba65367720d871f9d955ca3ef96358999182765 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:03 -0400 Subject: [SCSI] sym53c8xx: Stop overriding scsi_done Instead of telling the reset routine that the command completed from sym_eh_done, do it from sym_xpt_done. The 'to_do' element of the ucmd is redundant -- it serves only to tell whether eh_done is valid or not, and we can tell this by checking to see if it's NULL. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index b5e7c64..4de0692 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -134,8 +134,6 @@ static struct scsi_transport_template *sym2_transport_template = NULL; * Driver private area in the SCSI command structure. */ struct sym_ucmd { /* Override the SCSI pointer structure */ - unsigned char to_do; /* For error handling */ - void (*old_done)(struct scsi_cmnd *); /* For error handling */ struct completion *eh_done; /* For error handling */ }; @@ -147,6 +145,12 @@ struct sym_ucmd { /* Override the SCSI pointer structure */ */ void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *cmd) { + struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd); + BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd)); + + if (ucmd->eh_done) + complete(ucmd->eh_done); + scsi_dma_unmap(cmd); cmd->scsi_done(cmd); } @@ -586,26 +590,6 @@ static void sym53c8xx_timer(unsigned long npref) #define SYM_EH_HOST_RESET 3 /* - * What we will do regarding the involved SCSI command. - */ -#define SYM_EH_DO_IGNORE 0 -#define SYM_EH_DO_WAIT 2 - -/* - * scsi_done() alias when error recovery is in progress. - */ -static void sym_eh_done(struct scsi_cmnd *cmd) -{ - struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd); - BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd)); - - cmd->scsi_done = ucmd->old_done; - - if (ucmd->to_do == SYM_EH_DO_WAIT) - complete(ucmd->eh_done); -} - -/* * Generic method for our eh processing. * The 'op' argument tells what we have to do. */ @@ -615,7 +599,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd); struct Scsi_Host *host = cmd->device->host; SYM_QUEHEAD *qp; - int to_do = SYM_EH_DO_IGNORE; + int cmd_queued = 0; int sts = -1; struct completion eh_done; @@ -626,19 +610,11 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) { struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq); if (cp->cmd == cmd) { - to_do = SYM_EH_DO_WAIT; + cmd_queued = 1; break; } } - if (to_do == SYM_EH_DO_WAIT) { - init_completion(&eh_done); - ucmd->old_done = cmd->scsi_done; - ucmd->eh_done = &eh_done; - wmb(); - cmd->scsi_done = sym_eh_done; - } - /* Try to proceed the operation we have been asked for */ sts = -1; switch(op) { @@ -662,21 +638,21 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) } /* On error, restore everything and cross fingers :) */ - if (sts) { - cmd->scsi_done = ucmd->old_done; - to_do = SYM_EH_DO_IGNORE; - } - - ucmd->to_do = to_do; - spin_unlock_irq(host->host_lock); + if (sts) + cmd_queued = 0; - if (to_do == SYM_EH_DO_WAIT) { + if (cmd_queued) { + init_completion(&eh_done); + ucmd->eh_done = &eh_done; + spin_unlock_irq(host->host_lock); if (!wait_for_completion_timeout(&eh_done, 5*HZ)) { - ucmd->to_do = SYM_EH_DO_IGNORE; - wmb(); + ucmd->eh_done = NULL; sts = -2; } + } else { + spin_unlock_irq(host->host_lock); } + dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname, sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed"); return sts ? SCSI_FAILED : SCSI_SUCCESS; -- cgit v0.10.2 From d68cd75992f95d6977956fb227f02e6d532f3d26 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 5 Oct 2007 15:55:04 -0400 Subject: [SCSI] sym53c8xx: PCI Error Recovery support This patch adds the PCI error recovery callbacks to the Symbios SCSI device driver. It includes support for First Failure Data Capture. Signed-off-by: Linas Vepstas Assorted changes to initial patches, including returning IRQ_NONE from the interrupt handler if the device is offline and re-using the eh_done completion in the scsi error handler. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 4de0692..67a577d 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -134,7 +134,7 @@ static struct scsi_transport_template *sym2_transport_template = NULL; * Driver private area in the SCSI command structure. */ struct sym_ucmd { /* Override the SCSI pointer structure */ - struct completion *eh_done; /* For error handling */ + struct completion *eh_done; /* SCSI error handling */ }; #define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp)) @@ -556,6 +556,10 @@ static irqreturn_t sym53c8xx_intr(int irq, void *dev_id) { struct sym_hcb *np = dev_id; + /* Avoid spinloop trying to handle interrupts on frozen device */ + if (pci_channel_offline(np->s.device)) + return IRQ_NONE; + if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("["); spin_lock(np->s.host->host_lock); @@ -598,6 +602,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) struct sym_hcb *np = SYM_SOFTC_PTR(cmd); struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd); struct Scsi_Host *host = cmd->device->host; + struct pci_dev *pdev = np->s.device; SYM_QUEHEAD *qp; int cmd_queued = 0; int sts = -1; @@ -605,6 +610,38 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname); + /* We may be in an error condition because the PCI bus + * went down. In this case, we need to wait until the + * PCI bus is reset, the card is reset, and only then + * proceed with the scsi error recovery. There's no + * point in hurrying; take a leisurely wait. + */ +#define WAIT_FOR_PCI_RECOVERY 35 + if (pci_channel_offline(pdev)) { + struct host_data *hostdata = shost_priv(host); + struct completion *io_reset; + int finished_reset = 0; + init_completion(&eh_done); + spin_lock_irq(host->host_lock); + /* Make sure we didn't race */ + if (pci_channel_offline(pdev)) { + if (!hostdata->io_reset) + hostdata->io_reset = &eh_done; + io_reset = hostdata->io_reset; + } else { + io_reset = NULL; + } + + if (!pci_channel_offline(pdev)) + finished_reset = 1; + spin_unlock_irq(host->host_lock); + if (!finished_reset) + finished_reset = wait_for_completion_timeout(io_reset, + WAIT_FOR_PCI_RECOVERY*HZ); + if (!finished_reset) + return SCSI_FAILED; + } + spin_lock_irq(host->host_lock); /* This one is queued in some place -> to wait for completion */ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) { @@ -630,7 +667,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) break; case SYM_EH_HOST_RESET: sym_reset_scsi_bus(np, 0); - sym_start_up (np, 1); + sym_start_up(np, 1); sts = 0; break; default: @@ -1435,7 +1472,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, /* * Start the SCRIPTS. */ - sym_start_up (np, 1); + sym_start_up(np, 1); /* * Start the timer daemon @@ -1823,6 +1860,134 @@ static void __devexit sym2_remove(struct pci_dev *pdev) attach_count--; } +/** + * sym2_io_error_detected() - called when PCI error is detected + * @pdev: pointer to PCI device + * @state: current state of the PCI slot + */ +static pci_ers_result_t sym2_io_error_detected(struct pci_dev *pdev, + enum pci_channel_state state) +{ + /* If slot is permanently frozen, turn everything off */ + if (state == pci_channel_io_perm_failure) { + sym2_remove(pdev); + return PCI_ERS_RESULT_DISCONNECT; + } + + disable_irq(pdev->irq); + pci_disable_device(pdev); + + /* Request that MMIO be enabled, so register dump can be taken. */ + return PCI_ERS_RESULT_CAN_RECOVER; +} + +/** + * sym2_io_slot_dump - Enable MMIO and dump debug registers + * @pdev: pointer to PCI device + */ +static pci_ers_result_t sym2_io_slot_dump(struct pci_dev *pdev) +{ + struct sym_hcb *np = pci_get_drvdata(pdev); + + sym_dump_registers(np); + + /* Request a slot reset. */ + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * sym2_reset_workarounds - hardware-specific work-arounds + * + * This routine is similar to sym_set_workarounds(), except + * that, at this point, we already know that the device was + * succesfully intialized at least once before, and so most + * of the steps taken there are un-needed here. + */ +static void sym2_reset_workarounds(struct pci_dev *pdev) +{ + u_char revision; + u_short status_reg; + struct sym_chip *chip; + + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + chip = sym_lookup_chip_table(pdev->device, revision); + + /* Work around for errant bit in 895A, in a fashion + * similar to what is done in sym_set_workarounds(). + */ + pci_read_config_word(pdev, PCI_STATUS, &status_reg); + if (!(chip->features & FE_66MHZ) && (status_reg & PCI_STATUS_66MHZ)) { + status_reg = PCI_STATUS_66MHZ; + pci_write_config_word(pdev, PCI_STATUS, status_reg); + pci_read_config_word(pdev, PCI_STATUS, &status_reg); + } +} + +/** + * sym2_io_slot_reset() - called when the pci bus has been reset. + * @pdev: pointer to PCI device + * + * Restart the card from scratch. + */ +static pci_ers_result_t sym2_io_slot_reset(struct pci_dev *pdev) +{ + struct sym_hcb *np = pci_get_drvdata(pdev); + + printk(KERN_INFO "%s: recovering from a PCI slot reset\n", + sym_name(np)); + + if (pci_enable_device(pdev)) { + printk(KERN_ERR "%s: Unable to enable after PCI reset\n", + sym_name(np)); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_set_master(pdev); + enable_irq(pdev->irq); + + /* If the chip can do Memory Write Invalidate, enable it */ + if (np->features & FE_WRIE) { + if (pci_set_mwi(pdev)) + return PCI_ERS_RESULT_DISCONNECT; + } + + /* Perform work-arounds, analogous to sym_set_workarounds() */ + sym2_reset_workarounds(pdev); + + /* Perform host reset only on one instance of the card */ + if (PCI_FUNC(pdev->devfn) == 0) { + if (sym_reset_scsi_bus(np, 0)) { + printk(KERN_ERR "%s: Unable to reset scsi host\n", + sym_name(np)); + return PCI_ERS_RESULT_DISCONNECT; + } + sym_start_up(np, 1); + } + + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * sym2_io_resume() - resume normal ops after PCI reset + * @pdev: pointer to PCI device + * + * Called when the error recovery driver tells us that its + * OK to resume normal operation. Use completion to allow + * halted scsi ops to resume. + */ +static void sym2_io_resume(struct pci_dev *pdev) +{ + struct sym_hcb *np = pci_get_drvdata(pdev); + struct Scsi_Host *shost = np->s.host; + struct host_data *hostdata = shost_priv(shost); + + spin_lock_irq(shost->host_lock); + if (hostdata->io_reset) + complete_all(hostdata->io_reset); + hostdata->io_reset = NULL; + spin_unlock_irq(shost->host_lock); +} + static void sym2_get_signalling(struct Scsi_Host *shost) { struct sym_hcb *np = sym_get_hcb(shost); @@ -1985,11 +2150,19 @@ static struct pci_device_id sym2_id_table[] __devinitdata = { MODULE_DEVICE_TABLE(pci, sym2_id_table); +static struct pci_error_handlers sym2_err_handler = { + .error_detected = sym2_io_error_detected, + .mmio_enabled = sym2_io_slot_dump, + .slot_reset = sym2_io_slot_reset, + .resume = sym2_io_resume, +}; + static struct pci_driver sym2_driver = { .name = NAME53C8XX, .id_table = sym2_id_table, .probe = sym2_probe, .remove = __devexit_p(sym2_remove), + .err_handler = &sym2_err_handler, }; static int __init sym2_init(void) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index bea7bcc..d5ba5aa 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -40,6 +40,7 @@ #ifndef SYM_GLUE_H #define SYM_GLUE_H +#include #include #include #include @@ -220,6 +221,7 @@ struct sym_device { */ struct host_data { struct sym_hcb *ncb; + struct completion *io_reset; /* PCI error handling */ }; static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host) @@ -265,5 +267,6 @@ void sym_xpt_async_bus_reset(struct sym_hcb *np); void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target); int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp); void sym_log_bus_error(struct sym_hcb *np); +void sym_dump_registers(struct sym_hcb *np); #endif /* SYM_GLUE_H */ diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 21cd4c7..af24c44 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -1180,10 +1180,10 @@ static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat) scr_to_cpu((int) *(u32 *)(script_base + script_ofs))); } - printf ("%s: regdump:", sym_name(np)); - for (i=0; i<24;i++) - printf (" %02x", (unsigned)INB_OFF(np, i)); - printf (".\n"); + printf("%s: regdump:", sym_name(np)); + for (i = 0; i < 24; i++) + printf(" %02x", (unsigned)INB_OFF(np, i)); + printf(".\n"); /* * PCI BUS error. @@ -1192,6 +1192,16 @@ static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat) sym_log_bus_error(np); } +void sym_dump_registers(struct sym_hcb *np) +{ + u_short sist; + u_char dstat; + + sist = INW(np, nc_sist); + dstat = INB(np, nc_dstat); + sym_log_hard_error(np, sist, dstat); +} + static struct sym_chip sym_dev_table[] = { {PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, 64, FE_ERL} @@ -2809,6 +2819,13 @@ void sym_interrupt (struct sym_hcb *np) dstat |= INB(np, nc_dstat); istatc = INB(np, nc_istat); istat |= istatc; + + /* Prevent deadlock waiting on a condition that may + * never clear. */ + if (unlikely(sist == 0xffff && dstat == 0xff)) { + if (pci_channel_offline(np->s.device)) + return; + } } while (istatc & (SIP|DIP)); if (DEBUG_FLAGS & DEBUG_TINY) -- cgit v0.10.2 From bd678450bfbd4bb6543a7138d9ee3418c2a11e7c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:05 -0400 Subject: [SCSI] sym53c8xx: Use pdev->revision Auke missed the sym2 driver in his initial sweep. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c index 9916a2a..2be0ae1 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.c +++ b/drivers/scsi/sym53c8xx_2/sym_fw.c @@ -206,13 +206,13 @@ sym_fw2_patch(struct sym_hcb *np) * they are not desirable. See `sym_fw2.h' for more details. */ if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 && - np->revision_id < 0x1 && + np->s.device->revision < 0x1 && np->pciclk_khz < 60000)) { scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP); scripta0->datao_phase[1] = cpu_to_scr(0); } - if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 && - /* np->revision_id < 0xff */ 1)) { + if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 /* && + np->s.device->revision < 0xff */)) { scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP); scripta0->sel_done[1] = cpu_to_scr(0); } diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 67a577d..3ed3ed8 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1254,8 +1254,8 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len) info.pos = 0; copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, " - "revision id 0x%x\n", - np->s.chip_name, np->device_id, np->revision_id); + "revision id 0x%x\n", np->s.chip_name, + np->device_id, np->s.device->revision); copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n", pci_name(np->s.device), IRQ_PRM(np->s.device->irq)); copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n", @@ -1368,10 +1368,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, unsigned long flags; struct sym_fw *fw; - printk(KERN_INFO - "sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n", - unit, dev->chip.name, dev->chip.revision_id, - pci_name(pdev), IRQ_PRM(pdev->irq)); + printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n", + unit, dev->chip.name, pdev->revision, pci_name(pdev), + IRQ_PRM(pdev->irq)); /* * Get the firmware for this chip. @@ -1412,7 +1411,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, np->s.device = pdev; np->s.unit = unit; np->device_id = dev->chip.device_id; - np->revision_id = dev->chip.revision_id; np->features = dev->chip.features; np->clock_divn = dev->chip.nr_divisor; np->maxoffs = dev->chip.offset_max; @@ -1500,7 +1498,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, instance->transportt = sym2_transport_template; /* 53c896 rev 1 errata: DMA may not cross 16MB boundary */ - if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && np->revision_id < 2) + if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 2) instance->dma_boundary = 0xFFFFFF; spin_unlock_irqrestore(instance->host_lock, flags); @@ -1545,7 +1543,6 @@ static int __devinit sym_check_supported(struct sym_device *device) { struct sym_chip *chip; struct pci_dev *pdev = device->pdev; - u_char revision; unsigned long io_port = pci_resource_start(pdev, 0); int i; @@ -1565,14 +1562,12 @@ static int __devinit sym_check_supported(struct sym_device *device) * to our device structure so we can make it match the actual device * and options. */ - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); - chip = sym_lookup_chip_table(pdev->device, revision); + chip = sym_lookup_chip_table(pdev->device, pdev->revision); if (!chip) { dev_info(&pdev->dev, "device not supported\n"); return -ENODEV; } memcpy(&device->chip, chip, sizeof(device->chip)); - device->chip.revision_id = revision; return 0; } @@ -1613,7 +1608,7 @@ static int __devinit sym_set_workarounds(struct sym_device *device) * We must ensure the chip will use WRITE AND INVALIDATE. * The revision number limit is for now arbitrary. */ - if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && chip->revision_id < 0x4) { + if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 0x4) { chip->features |= (FE_WRIE | FE_CLSE); } @@ -1905,12 +1900,10 @@ static pci_ers_result_t sym2_io_slot_dump(struct pci_dev *pdev) */ static void sym2_reset_workarounds(struct pci_dev *pdev) { - u_char revision; u_short status_reg; struct sym_chip *chip; - pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); - chip = sym_lookup_chip_table(pdev->device, revision); + chip = sym_lookup_chip_table(pdev->device, pdev->revision); /* Work around for errant bit in 895A, in a fashion * similar to what is done in sym_set_workarounds(). diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index af24c44..9f4198c 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -805,7 +805,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru * are used. Disable internal cycles. */ if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 && - np->revision_id < 0x1) + np->s.device->revision < 0x1) np->rv_ccntl0 |= DILS; /* @@ -829,9 +829,9 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru * LOAD/STORE instructions does not need this work-around. */ if ((np->device_id == PCI_DEVICE_ID_NCR_53C810 && - np->revision_id >= 0x10 && np->revision_id <= 0x11) || + np->s.device->revision >= 0x10 && np->s.device->revision <= 0x11) || (np->device_id == PCI_DEVICE_ID_NCR_53C860 && - np->revision_id <= 0x1)) + np->s.device->revision <= 0x1)) np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP); /* @@ -1809,7 +1809,7 @@ void sym_start_up (struct sym_hcb *np, int reason) * I just don't want. :) */ if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 && - np->revision_id < 1) + np->s.device->revision < 1) OUTB(np, nc_stest1, INB(np, nc_stest1) | 0x30); /* diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index 79ab6a1..3aa8060 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -919,7 +919,6 @@ struct sym_hcb { * General controller parameters and configuration. */ u_short device_id; /* PCI device id */ - u_char revision_id; /* PCI device revision id */ u_int features; /* Chip features map */ u_char myaddr; /* SCSI id of the adapter */ u_char maxburst; /* log base 2 of dwords burst */ -- cgit v0.10.2 From e58bc06ed071e43bef4e2f94340853761a4bf034 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:06 -0400 Subject: [SCSI] sym53c8xx: Remove ->device_id Following the same path as ->revision_id, remove ->device_id Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c index 2be0ae1..3d4db80 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.c +++ b/drivers/scsi/sym53c8xx_2/sym_fw.c @@ -205,13 +205,13 @@ sym_fw2_patch(struct sym_hcb *np) * Remove a couple of work-arounds specific to C1010 if * they are not desirable. See `sym_fw2.h' for more details. */ - if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 && + if (!(np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_66 && np->s.device->revision < 0x1 && np->pciclk_khz < 60000)) { scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP); scripta0->datao_phase[1] = cpu_to_scr(0); } - if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 /* && + if (!(np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_33 /* && np->s.device->revision < 0xff */)) { scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP); scripta0->sel_done[1] = cpu_to_scr(0); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 3ed3ed8..cbe31f2 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1255,7 +1255,7 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len) copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, " "revision id 0x%x\n", np->s.chip_name, - np->device_id, np->s.device->revision); + np->s.device->device, np->s.device->revision); copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n", pci_name(np->s.device), IRQ_PRM(np->s.device->irq)); copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n", @@ -1410,7 +1410,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, np->verbose = sym_driver_setup.verbose; np->s.device = pdev; np->s.unit = unit; - np->device_id = dev->chip.device_id; np->features = dev->chip.features; np->clock_divn = dev->chip.nr_divisor; np->maxoffs = dev->chip.offset_max; @@ -1528,7 +1527,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, static void __devinit sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp) { devp->nvram = nvp; - devp->device_id = devp->chip.device_id; nvp->type = 0; sym_read_nvram(devp, nvp); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index d5ba5aa..b961f70 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -212,7 +212,6 @@ struct sym_device { } s; struct sym_chip chip; struct sym_nvram *nvram; - u_short device_id; u_char host_id; }; diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 9f4198c..5443394 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -804,7 +804,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru * In dual channel mode, contention occurs if internal cycles * are used. Disable internal cycles. */ - if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 && + if (np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_33 && np->s.device->revision < 0x1) np->rv_ccntl0 |= DILS; @@ -828,9 +828,9 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru * this driver. The generic ncr driver that does not use * LOAD/STORE instructions does not need this work-around. */ - if ((np->device_id == PCI_DEVICE_ID_NCR_53C810 && + if ((np->s.device->device == PCI_DEVICE_ID_NCR_53C810 && np->s.device->revision >= 0x10 && np->s.device->revision <= 0x11) || - (np->device_id == PCI_DEVICE_ID_NCR_53C860 && + (np->s.device->device == PCI_DEVICE_ID_NCR_53C860 && np->s.device->revision <= 0x1)) np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP); @@ -897,7 +897,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru if ((SYM_SETUP_SCSI_LED || (nvram->type == SYM_SYMBIOS_NVRAM || (nvram->type == SYM_TEKRAM_NVRAM && - np->device_id == PCI_DEVICE_ID_NCR_53C895))) && + np->s.device->device == PCI_DEVICE_ID_NCR_53C895))) && !(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01)) np->features |= FE_LED0; @@ -1798,7 +1798,7 @@ void sym_start_up (struct sym_hcb *np, int reason) /* * For now, disable AIP generation on C1010-66. */ - if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66) + if (np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_66) OUTB(np, nc_aipcntl1, DISAIP); /* @@ -1808,7 +1808,7 @@ void sym_start_up (struct sym_hcb *np, int reason) * that from SCRIPTS for each selection/reselection, but * I just don't want. :) */ - if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 && + if (np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_33 && np->s.device->revision < 1) OUTB(np, nc_stest1, INB(np, nc_stest1) | 0x30); @@ -1817,9 +1817,9 @@ void sym_start_up (struct sym_hcb *np, int reason) * Disable overlapped arbitration for some dual function devices, * regardless revision id (kind of post-chip-design feature. ;-)) */ - if (np->device_id == PCI_DEVICE_ID_NCR_53C875) + if (np->s.device->device == PCI_DEVICE_ID_NCR_53C875) OUTB(np, nc_ctest0, (1<<5)); - else if (np->device_id == PCI_DEVICE_ID_NCR_53C896) + else if (np->s.device->device == PCI_DEVICE_ID_NCR_53C896) np->rv_ccntl0 |= DPR; /* diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index 3aa8060..b8908e1 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -918,7 +918,6 @@ struct sym_hcb { /* * General controller parameters and configuration. */ - u_short device_id; /* PCI device id */ u_int features; /* Chip features map */ u_char myaddr; /* SCSI id of the adapter */ u_char maxburst; /* log base 2 of dwords burst */ diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c index 15d6929..5662fbb 100644 --- a/drivers/scsi/sym53c8xx_2/sym_nvram.c +++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c @@ -696,7 +696,7 @@ static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram) u_short csum; int x; - switch (np->device_id) { + switch (np->pdev->device) { case PCI_DEVICE_ID_NCR_53C885: case PCI_DEVICE_ID_NCR_53C895: case PCI_DEVICE_ID_NCR_53C896: -- cgit v0.10.2 From 8637baa3609afff9fe4c65ad4c64d72484c699fc Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:07 -0400 Subject: [SCSI] sym53c8xx: Remove io_ws, mmio_ws and ram_ws elements These struct elements record info that is never needed Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index cbe31f2..6e768c5 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1432,17 +1432,14 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, np->mmio_ba = (u32)dev->mmio_base; np->s.ioaddr = dev->s.ioaddr; np->s.ramaddr = dev->s.ramaddr; - np->s.io_ws = (np->features & FE_IO256) ? 256 : 128; /* * Map on-chip RAM if present and supported. */ if (!(np->features & FE_RAM)) dev->ram_base = 0; - if (dev->ram_base) { + if (dev->ram_base) np->ram_ba = (u32)dev->ram_base; - np->ram_ws = (np->features & FE_RAM8K) ? 8192 : 4096; - } if (sym_hcb_attach(instance, fw, dev->nvram)) goto attach_failed; diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index b961f70..ab2de1c 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -184,7 +184,6 @@ struct sym_shcb { void __iomem * ioaddr; /* MMIO kernel io address */ void __iomem * ramaddr; /* RAM kernel io address */ - u_short io_ws; /* IO window size */ struct timer_list timer; /* Timer handler link header */ u_long lasttime; diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 5443394..39f84bb 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -1910,7 +1910,7 @@ void sym_start_up (struct sym_hcb *np, int reason) if (sym_verbose >= 2) printf("%s: Downloading SCSI SCRIPTS.\n", sym_name(np)); memcpy_toio(np->s.ramaddr, np->scripta0, np->scripta_sz); - if (np->ram_ws == 8192) { + if (np->features & FE_RAM8K) { memcpy_toio(np->s.ramaddr + 4096, np->scriptb0, np->scriptb_sz); phys = scr_to_cpu(np->scr_ram_seg); OUTL(np, nc_mmws, phys); @@ -5595,16 +5595,13 @@ int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram np->scriptz_ba = vtobus(np->scriptz0); if (np->ram_ba) { - np->scripta_ba = np->ram_ba; + np->scripta_ba = np->ram_ba; if (np->features & FE_RAM8K) { - np->ram_ws = 8192; np->scriptb_ba = np->scripta_ba + 4096; #if 0 /* May get useful for 64 BIT PCI addressing */ np->scr_ram_seg = cpu_to_scr(np->scripta_ba >> 32); #endif } - else - np->ram_ws = 4096; } /* diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index b8908e1..f76b27f 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -883,10 +883,7 @@ struct sym_hcb { * Physical bus addresses of the chip. */ u32 mmio_ba; /* MMIO 32 bit BUS address */ - int mmio_ws; /* MMIO Window size */ - u32 ram_ba; /* RAM 32 bit BUS address */ - int ram_ws; /* RAM window size */ /* * SCRIPTS virtual and physical bus addresses. -- cgit v0.10.2 From a44131b35ec1a46ed75014d818cb9d5706117b49 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:08 -0400 Subject: [SCSI] sym53c8xx: Remove tag_ctrl module parameter With sysfs making these options tunable at runtime, there's no justification for keeping this horrendously complex specification string around. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt index 3d9f06b..49ea5c5 100644 --- a/Documentation/scsi/sym53c8xx_2.txt +++ b/Documentation/scsi/sym53c8xx_2.txt @@ -449,25 +449,14 @@ options as above. cmd_per_lun=#tags (#tags > 1) tagged command queuing enabled #tags will be truncated to the max queued commands configuration parameter. -10.2.2 Detailed control of tagged commands - This option allows you to specify a command queue depth for each device - that supports tagged command queueing. - Example: - tag_ctrl=10/t2t3q16-t5q24/t1u2q32 - will set devices queue depth as follow: - - controller #0 target #2 and target #3 -> 16 commands, - - controller #0 target #5 -> 24 commands, - - controller #1 target #1 logical unit #2 -> 32 commands, - - all other logical units (all targets, all controllers) -> 10 commands. - -10.2.3 Burst max +10.2.2 Burst max burst=0 burst disabled burst=255 get burst length from initial IO register settings. burst=#x burst enabled (1<<#x burst transfers max) #x is an integer value which is log base 2 of the burst transfers max. By default the driver uses the maximum value supported by the chip. -10.2.4 LED support +10.2.3 LED support led=1 enable LED support led=0 disable LED support Do not enable LED support if your scsi board does not use SDMS BIOS. @@ -560,9 +549,9 @@ Previously, the sym2 driver accepted arguments of the form sym53c8xx=tags:4,sync:10,debug:0x200 As a result of the new module parameters, this is no longer available. -Most of the options have remained the same, but tags has split into -cmd_per_lun and tag_ctrl for its two different purposes. The sample above -would be specified as: +Most of the options have remained the same, but tags has become +cmd_per_lun to reflect its different purposes. The sample above would +be specified as: modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200 or on the kernel boot line as: diff --git a/drivers/scsi/sym53c8xx_2/sym53c8xx.h b/drivers/scsi/sym53c8xx_2/sym53c8xx.h index 7519728..62d29cf 100644 --- a/drivers/scsi/sym53c8xx_2/sym53c8xx.h +++ b/drivers/scsi/sym53c8xx_2/sym53c8xx.h @@ -127,7 +127,6 @@ struct sym_driver_setup { u_char settle_delay; u_char use_nvram; u_long excludes[8]; - char tag_ctrl[100]; }; #define SYM_SETUP_MAX_TAG sym_driver_setup.max_tag diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 6e768c5..c1d9f69 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -63,7 +63,6 @@ unsigned int sym_debug_flags = 0; static char *excl_string; static char *safe_string; module_param_named(cmd_per_lun, sym_driver_setup.max_tag, ushort, 0); -module_param_string(tag_ctrl, sym_driver_setup.tag_ctrl, 100, 0); module_param_named(burst, sym_driver_setup.burst_order, byte, 0); module_param_named(led, sym_driver_setup.scsi_led, byte, 0); module_param_named(diff, sym_driver_setup.scsi_diff, byte, 0); @@ -78,7 +77,6 @@ module_param_named(excl, excl_string, charp, 0); module_param_named(safe, safe_string, charp, 0); MODULE_PARM_DESC(cmd_per_lun, "The maximum number of tags to use by default"); -MODULE_PARM_DESC(tag_ctrl, "More detailed control over tags per LUN"); MODULE_PARM_DESC(burst, "Maximum burst. 0 to disable, 255 to read from registers"); MODULE_PARM_DESC(led, "Set to 1 to enable LED support"); MODULE_PARM_DESC(diff, "0 for no differential mode, 1 for BIOS, 2 for always, 3 for not GPIO3"); @@ -744,59 +742,6 @@ static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags) } } -/* - * Linux select queue depths function - */ -#define DEF_DEPTH (sym_driver_setup.max_tag) -#define ALL_TARGETS -2 -#define NO_TARGET -1 -#define ALL_LUNS -2 -#define NO_LUN -1 - -static int device_queue_depth(struct sym_hcb *np, int target, int lun) -{ - int c, h, t, u, v; - char *p = sym_driver_setup.tag_ctrl; - char *ep; - - h = -1; - t = NO_TARGET; - u = NO_LUN; - while ((c = *p++) != 0) { - v = simple_strtoul(p, &ep, 0); - switch(c) { - case '/': - ++h; - t = ALL_TARGETS; - u = ALL_LUNS; - break; - case 't': - if (t != target) - t = (target == v) ? v : NO_TARGET; - u = ALL_LUNS; - break; - case 'u': - if (u != lun) - u = (lun == v) ? v : NO_LUN; - break; - case 'q': - if (h == np->s.unit && - (t == ALL_TARGETS || t == target) && - (u == ALL_LUNS || u == lun)) - return v; - break; - case '-': - t = ALL_TARGETS; - u = ALL_LUNS; - break; - default: - break; - } - p = ep; - } - return DEF_DEPTH; -} - static int sym53c8xx_slave_alloc(struct scsi_device *sdev) { struct sym_hcb *np = sym_get_hcb(sdev->host); @@ -861,21 +806,16 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev) * Use at least 2. * Donnot use more than our maximum. */ - reqtags = device_queue_depth(np, sdev->id, sdev->lun); + reqtags = sym_driver_setup.max_tag; if (reqtags > tp->usrtags) reqtags = tp->usrtags; if (!sdev->tagged_supported) reqtags = 0; -#if 1 /* Avoid to locally queue commands for no good reasons */ if (reqtags > SYM_CONF_MAX_TAG) reqtags = SYM_CONF_MAX_TAG; - depth_to_use = (reqtags ? reqtags : 2); -#else - depth_to_use = (reqtags ? SYM_CONF_MAX_TAG : 2); -#endif + depth_to_use = reqtags ? reqtags : 2; scsi_adjust_queue_depth(sdev, - (sdev->tagged_supported ? - MSG_SIMPLE_TAG : 0), + sdev->tagged_supported ? MSG_SIMPLE_TAG : 0, depth_to_use); lp->s.scdev_depth = depth_to_use; sym_tune_dev_queuing(tp, sdev->lun, reqtags); -- cgit v0.10.2 From 4d85b471593d03e141f9160a58574b9204363267 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:09 -0400 Subject: [SCSI] sym53c8xx: Simplify DAC DMA handling By introducing the use_dac(), set_dac() and DMA_DAC_MASK macros, we can eliminate a lot of ifdefs from the code. We now rely on the compiler to optimise away a few things that we'd formerly relied on the preprocessor to do. This makes sym_setup_bus_dma_mask() small enough to inline into its only caller. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c index 3d4db80..aa230d2 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.c +++ b/drivers/scsi/sym53c8xx_2/sym_fw.c @@ -167,7 +167,7 @@ sym_fw2_patch(struct sym_hcb *np) * Remove useless 64 bit DMA specific SCRIPTS, * when this feature is not available. */ - if (!np->use_dac) { + if (!use_dac(np)) { scripta0->is_dmap_dirty[0] = cpu_to_scr(SCR_NO_OP); scripta0->is_dmap_dirty[1] = 0; scripta0->is_dmap_dirty[2] = cpu_to_scr(SCR_NO_OP); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index c1d9f69..5501297 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -1265,31 +1265,6 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev) } /* - * Ask/tell the system about DMA addressing. - */ -static int sym_setup_bus_dma_mask(struct sym_hcb *np) -{ -#if SYM_CONF_DMA_ADDRESSING_MODE > 0 -#if SYM_CONF_DMA_ADDRESSING_MODE == 1 -#define DMA_DAC_MASK DMA_40BIT_MASK -#elif SYM_CONF_DMA_ADDRESSING_MODE == 2 -#define DMA_DAC_MASK DMA_64BIT_MASK -#endif - if ((np->features & FE_DAC) && - !pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) { - np->use_dac = 1; - return 0; - } -#endif - - if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK)) - return 0; - - printf_warning("%s: No suitable DMA available\n", sym_name(np)); - return -1; -} - -/* * Host attach and initialisations. * * Allocate host data and ncb structure. @@ -1362,8 +1337,13 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name)); sprintf(np->s.inst_name, "sym%d", np->s.unit); - if (sym_setup_bus_dma_mask(np)) + if ((SYM_CONF_DMA_ADDRESSING_MODE > 0) && (np->features & FE_DAC) && + !pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) { + set_dac(np); + } else if (pci_set_dma_mask(np->s.device, DMA_32BIT_MASK)) { + printf_warning("%s: No suitable DMA available\n", sym_name(np)); goto attach_failed; + } /* * Try to map the controller chip to diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 39f84bb..5d0d356 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -778,19 +778,12 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru * 64 bit addressing (895A/896/1010) ? */ if (np->features & FE_DAC) { -#if SYM_CONF_DMA_ADDRESSING_MODE == 0 - np->rv_ccntl1 |= (DDAC); -#elif SYM_CONF_DMA_ADDRESSING_MODE == 1 - if (!np->use_dac) - np->rv_ccntl1 |= (DDAC); - else - np->rv_ccntl1 |= (XTIMOD | EXTIBMV); -#elif SYM_CONF_DMA_ADDRESSING_MODE == 2 - if (!np->use_dac) - np->rv_ccntl1 |= (DDAC); - else - np->rv_ccntl1 |= (0 | EXTIBMV); -#endif + if (!use_dac(np)) + np->rv_ccntl1 |= (DDAC); + else if (SYM_CONF_DMA_ADDRESSING_MODE == 1) + np->rv_ccntl1 |= (XTIMOD | EXTIBMV); + else if (SYM_CONF_DMA_ADDRESSING_MODE == 2) + np->rv_ccntl1 |= (0 | EXTIBMV); } /* @@ -1322,7 +1315,7 @@ int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s) { int i; - if (!np->use_dac) + if (!use_dac(np)) goto weird; /* Look up existing mappings */ @@ -1837,7 +1830,7 @@ void sym_start_up (struct sym_hcb *np, int reason) * Set up scratch C and DRS IO registers to map the 32 bit * DMA address range our data structures are located in. */ - if (np->use_dac) { + if (use_dac(np)) { np->dmap_bah[0] = 0; /* ??? */ OUTL(np, nc_scrx[0], np->dmap_bah[0]); OUTL(np, nc_drs, np->dmap_bah[0]); diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index f76b27f..4354571 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -1026,6 +1026,14 @@ struct sym_hcb { #endif }; +#if SYM_CONF_DMA_ADDRESSING_MODE == 0 +#define use_dac(np) 0 +#define set_dac(np) do { } while (0) +#else +#define use_dac(np) (np)->use_dac +#define set_dac(np) (np)->use_dac = 1 +#endif + #define HCB_BA(np, lbl) (np->hcb_ba + offsetof(struct sym_hcb, lbl)) @@ -1068,18 +1076,21 @@ int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram */ #if SYM_CONF_DMA_ADDRESSING_MODE == 0 +#define DMA_DAC_MASK DMA_32BIT_MASK #define sym_build_sge(np, data, badd, len) \ do { \ (data)->addr = cpu_to_scr(badd); \ (data)->size = cpu_to_scr(len); \ } while (0) #elif SYM_CONF_DMA_ADDRESSING_MODE == 1 +#define DMA_DAC_MASK DMA_40BIT_MASK #define sym_build_sge(np, data, badd, len) \ do { \ (data)->addr = cpu_to_scr(badd); \ (data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \ } while (0) #elif SYM_CONF_DMA_ADDRESSING_MODE == 2 +#define DMA_DAC_MASK DMA_64BIT_MASK int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s); static __inline void sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len) -- cgit v0.10.2 From 3fb364e089e05c35ead55a08d56d3004193681f6 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:10 -0400 Subject: [SCSI] sym53c8xx: Use scmd_printk where appropriate If we have a scsi_cmnd, it gives the user more information than the sym_name, and maybe the target. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 5501297..84a0fc5 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -392,7 +392,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s */ switch (dir) { case DMA_BIDIRECTIONAL: - printk("%s: got DMA_BIDIRECTIONAL command", sym_name(np)); + scmd_printk(KERN_INFO, cmd, "got DMA_BIDIRECTIONAL command"); sym_set_cam_status(cmd, DID_ERROR); goto out_abort; case DMA_TO_DEVICE: @@ -606,7 +606,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) int sts = -1; struct completion eh_done; - dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname); + scmd_printk(KERN_WARNING, cmd, "%s operation started.\n", opname); /* We may be in an error condition because the PCI bus * went down. In this case, we need to wait until the diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 5d0d356..13fd5b2 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -52,7 +52,7 @@ * Needed function prototypes. */ static void sym_int_ma (struct sym_hcb *np); -static void sym_int_sir (struct sym_hcb *np); +static void sym_int_sir(struct sym_hcb *); static struct sym_ccb *sym_alloc_ccb(struct sym_hcb *np); static struct sym_ccb *sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa); static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln); @@ -1522,7 +1522,8 @@ void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp) np->squeueput = qidx; if (DEBUG_FLAGS & DEBUG_QUEUE) - printf ("%s: queuepos=%d.\n", sym_name (np), np->squeueput); + scmd_printk(KERN_DEBUG, cp->cmd, "queuepos=%d\n", + np->squeueput); /* * Script processor may be waiting for reselect. @@ -2852,7 +2853,7 @@ void sym_interrupt (struct sym_hcb *np) !(dstat & (MDPE|BF|ABRT|IID))) { if (sist & PAR) sym_int_par (np, sist); else if (sist & MA) sym_int_ma (np); - else if (dstat & SIR) sym_int_sir (np); + else if (dstat & SIR) sym_int_sir(np); else if (dstat & SSI) OUTONB_STD(); else goto unknown_int; return; @@ -4314,7 +4315,7 @@ static void sym_nego_rejected(struct sym_hcb *np, struct sym_tcb *tp, struct sym /* * chip exception handler for programmed interrupts. */ -static void sym_int_sir (struct sym_hcb *np) +static void sym_int_sir(struct sym_hcb *np) { u_char num = INB(np, nc_dsps); u32 dsa = INL(np, nc_dsa); @@ -4353,31 +4354,30 @@ static void sym_int_sir (struct sym_hcb *np) return; /* * The device didn't go to MSG OUT phase after having - * been selected with ATN. We donnot want to handle - * that. + * been selected with ATN. We do not want to handle that. */ case SIR_SEL_ATN_NO_MSG_OUT: - printf ("%s:%d: No MSG OUT phase after selection with ATN.\n", - sym_name (np), target); + scmd_printk(KERN_WARNING, cp->cmd, + "No MSG OUT phase after selection with ATN\n"); goto out_stuck; /* * The device didn't switch to MSG IN phase after - * having reseleted the initiator. + * having reselected the initiator. */ case SIR_RESEL_NO_MSG_IN: - printf ("%s:%d: No MSG IN phase after reselection.\n", - sym_name (np), target); + scmd_printk(KERN_WARNING, cp->cmd, + "No MSG IN phase after reselection\n"); goto out_stuck; /* * After reselection, the device sent a message that wasn't * an IDENTIFY. */ case SIR_RESEL_NO_IDENTIFY: - printf ("%s:%d: No IDENTIFY after reselection.\n", - sym_name (np), target); + scmd_printk(KERN_WARNING, cp->cmd, + "No IDENTIFY after reselection\n"); goto out_stuck; /* - * The device reselected a LUN we donnot know about. + * The device reselected a LUN we do not know about. */ case SIR_RESEL_BAD_LUN: np->msgout[0] = M_RESET; @@ -4390,8 +4390,7 @@ static void sym_int_sir (struct sym_hcb *np) np->msgout[0] = M_ABORT; goto out; /* - * The device reselected for a tagged nexus that we donnot - * have. + * The device reselected for a tagged nexus that we do not have. */ case SIR_RESEL_BAD_I_T_L_Q: np->msgout[0] = M_ABORT_TAG; @@ -4403,8 +4402,8 @@ static void sym_int_sir (struct sym_hcb *np) case SIR_RESEL_ABORTED: np->lastmsg = np->msgout[0]; np->msgout[0] = M_NOOP; - printf ("%s:%d: message %x sent on bad reselection.\n", - sym_name (np), target, np->lastmsg); + scmd_printk(KERN_WARNING, cp->cmd, + "message %x sent on bad reselection\n", np->lastmsg); goto out; /* * The SCRIPTS let us know that a message has been -- cgit v0.10.2 From 8022fbdacb0e9193a5dfb666479d1fc2ca63ecf1 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:11 -0400 Subject: [SCSI] sym53c8xx: Get rid of IRQ_FMT and IRQ_PRM These macros aren't needed any more. They used to be used for SPARC. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 84a0fc5..9521f0e 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -54,9 +54,6 @@ #define NAME53C "sym53c" #define NAME53C8XX "sym53c8xx" -#define IRQ_FMT "%d" -#define IRQ_PRM(x) (x) - struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP; unsigned int sym_debug_flags = 0; @@ -1196,8 +1193,8 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len) copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, " "revision id 0x%x\n", np->s.chip_name, np->s.device->device, np->s.device->revision); - copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n", - pci_name(np->s.device), IRQ_PRM(np->s.device->irq)); + copy_info(&info, "At PCI address %s, IRQ %u\n", + pci_name(np->s.device), np->s.device->irq); copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n", (int) (np->minsync_dt ? np->minsync_dt : np->minsync), np->maxwide ? "Wide" : "Narrow", @@ -1283,9 +1280,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, unsigned long flags; struct sym_fw *fw; - printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n", + printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq %u\n", unit, dev->chip.name, pdev->revision, pci_name(pdev), - IRQ_PRM(pdev->irq)); + pdev->irq); /* * Get the firmware for this chip. @@ -1370,7 +1367,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, * we do not want to share the INTR line at all. */ if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX, np)) { - printf_err("%s: request irq %d failure\n", + printf_err("%s: request irq %u failure\n", sym_name(np), pdev->irq); goto attach_failed; } -- cgit v0.10.2 From 99c9e0a1d6cfe1ba1169a7a81435ee85bc00e4a1 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:12 -0400 Subject: [SCSI] sym53c8xx: Make interrupt handler capable of returning IRQ_NONE Make sym_interrupt return an irqreturn_t instead of void, and take a Scsi_Host instead of a sym_hcb. Pass the Scsi_Host to the interrupt handler instead of the sym_hcb. Rename the host_data to sym_data. Keep a pci_dev pointer in the sym_data. Rename the Scsi_Host from instance to shost. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 9521f0e..1c18b3b 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -39,7 +39,6 @@ */ #include #include -#include #include #include #include @@ -549,21 +548,23 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd, */ static irqreturn_t sym53c8xx_intr(int irq, void *dev_id) { - struct sym_hcb *np = dev_id; + struct Scsi_Host *shost = dev_id; + struct sym_data *sym_data = shost_priv(shost); + irqreturn_t result; /* Avoid spinloop trying to handle interrupts on frozen device */ - if (pci_channel_offline(np->s.device)) + if (pci_channel_offline(sym_data->pdev)) return IRQ_NONE; if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("["); - spin_lock(np->s.host->host_lock); - sym_interrupt(np); - spin_unlock(np->s.host->host_lock); + spin_lock(shost->host_lock); + result = sym_interrupt(shost); + spin_unlock(shost->host_lock); if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n"); - return IRQ_HANDLED; + return result; } /* @@ -613,22 +614,19 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) */ #define WAIT_FOR_PCI_RECOVERY 35 if (pci_channel_offline(pdev)) { - struct host_data *hostdata = shost_priv(host); + struct sym_data *sym_data = shost_priv(host); struct completion *io_reset; int finished_reset = 0; init_completion(&eh_done); spin_lock_irq(host->host_lock); /* Make sure we didn't race */ if (pci_channel_offline(pdev)) { - if (!hostdata->io_reset) - hostdata->io_reset = &eh_done; - io_reset = hostdata->io_reset; + if (!sym_data->io_reset) + sym_data->io_reset = &eh_done; + io_reset = sym_data->io_reset; } else { - io_reset = NULL; - } - - if (!pci_channel_offline(pdev)) finished_reset = 1; + } spin_unlock_irq(host->host_lock); if (!finished_reset) finished_reset = wait_for_completion_timeout(io_reset, @@ -1273,9 +1271,9 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev) static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, int unit, struct sym_device *dev) { - struct host_data *host_data; + struct sym_data *sym_data; struct sym_hcb *np = NULL; - struct Scsi_Host *instance = NULL; + struct Scsi_Host *shost; struct pci_dev *pdev = dev->pdev; unsigned long flags; struct sym_fw *fw; @@ -1289,15 +1287,12 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, */ fw = sym_find_firmware(&dev->chip); if (!fw) - goto attach_failed; + return NULL; - /* - * Allocate host_data structure - */ - instance = scsi_host_alloc(tpnt, sizeof(*host_data)); - if (!instance) - goto attach_failed; - host_data = (struct host_data *) instance->hostdata; + shost = scsi_host_alloc(tpnt, sizeof(*sym_data)); + if (!shost) + return NULL; + sym_data = shost_priv(shost); /* * Allocate immediately the host control block, @@ -1310,8 +1305,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, goto attach_failed; np->s.device = pdev; np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */ - host_data->ncb = np; - np->s.host = instance; + sym_data->ncb = np; + sym_data->pdev = pdev; + np->s.host = shost; pci_set_drvdata(pdev, np); @@ -1358,7 +1354,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, if (dev->ram_base) np->ram_ba = (u32)dev->ram_base; - if (sym_hcb_attach(instance, fw, dev->nvram)) + if (sym_hcb_attach(shost, fw, dev->nvram)) goto attach_failed; /* @@ -1366,7 +1362,8 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, * If we synchonize the C code with SCRIPTS on interrupt, * we do not want to share the INTR line at all. */ - if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX, np)) { + if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX, + shost)) { printf_err("%s: request irq %u failure\n", sym_name(np), pdev->irq); goto attach_failed; @@ -1376,7 +1373,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, * After SCSI devices have been opened, we cannot * reset the bus safely, so we do it here. */ - spin_lock_irqsave(instance->host_lock, flags); + spin_lock_irqsave(shost->host_lock, flags); if (sym_reset_scsi_bus(np, 0)) goto reset_failed; @@ -1398,37 +1395,37 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, * Fill Linux host instance structure * and return success. */ - instance->max_channel = 0; - instance->this_id = np->myaddr; - instance->max_id = np->maxwide ? 16 : 8; - instance->max_lun = SYM_CONF_MAX_LUN; - instance->unique_id = pci_resource_start(pdev, 0); - instance->cmd_per_lun = SYM_CONF_MAX_TAG; - instance->can_queue = (SYM_CONF_MAX_START-2); - instance->sg_tablesize = SYM_CONF_MAX_SG; - instance->max_cmd_len = 16; + shost->max_channel = 0; + shost->this_id = np->myaddr; + shost->max_id = np->maxwide ? 16 : 8; + shost->max_lun = SYM_CONF_MAX_LUN; + shost->unique_id = pci_resource_start(pdev, 0); + shost->cmd_per_lun = SYM_CONF_MAX_TAG; + shost->can_queue = (SYM_CONF_MAX_START-2); + shost->sg_tablesize = SYM_CONF_MAX_SG; + shost->max_cmd_len = 16; BUG_ON(sym2_transport_template == NULL); - instance->transportt = sym2_transport_template; + shost->transportt = sym2_transport_template; /* 53c896 rev 1 errata: DMA may not cross 16MB boundary */ if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 2) - instance->dma_boundary = 0xFFFFFF; + shost->dma_boundary = 0xFFFFFF; - spin_unlock_irqrestore(instance->host_lock, flags); + spin_unlock_irqrestore(shost->host_lock, flags); - return instance; + return shost; reset_failed: printf_err("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, " "TERMINATION, DEVICE POWER etc.!\n", sym_name(np)); - spin_unlock_irqrestore(instance->host_lock, flags); + spin_unlock_irqrestore(shost->host_lock, flags); attach_failed: - if (!instance) + if (!shost) return NULL; printf_info("%s: giving up ...\n", sym_name(np)); if (np) sym_free_resources(np, pdev); - scsi_host_put(instance); + scsi_host_put(shost); return NULL; } @@ -1702,7 +1699,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev, { struct sym_device sym_dev; struct sym_nvram nvram; - struct Scsi_Host *instance; + struct Scsi_Host *shost; memset(&sym_dev, 0, sizeof(sym_dev)); memset(&nvram, 0, sizeof(nvram)); @@ -1729,13 +1726,13 @@ static int __devinit sym2_probe(struct pci_dev *pdev, sym_get_nvram(&sym_dev, &nvram); - instance = sym_attach(&sym2_template, attach_count, &sym_dev); - if (!instance) + shost = sym_attach(&sym2_template, attach_count, &sym_dev); + if (!shost) goto free; - if (scsi_add_host(instance, &pdev->dev)) + if (scsi_add_host(shost, &pdev->dev)) goto detach; - scsi_scan_host(instance); + scsi_scan_host(shost); attach_count++; @@ -1884,12 +1881,12 @@ static void sym2_io_resume(struct pci_dev *pdev) { struct sym_hcb *np = pci_get_drvdata(pdev); struct Scsi_Host *shost = np->s.host; - struct host_data *hostdata = shost_priv(shost); + struct sym_data *sym_data = shost_priv(shost); spin_lock_irq(shost->host_lock); - if (hostdata->io_reset) - complete_all(hostdata->io_reset); - hostdata->io_reset = NULL; + if (sym_data->io_reset) + complete_all(sym_data->io_reset); + sym_data->io_reset = NULL; spin_unlock_irq(shost->host_lock); } diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index ab2de1c..98261a5 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -217,14 +218,15 @@ struct sym_device { /* * Driver host data structure. */ -struct host_data { +struct sym_data { struct sym_hcb *ncb; struct completion *io_reset; /* PCI error handling */ + struct pci_dev *pdev; }; static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host) { - return ((struct host_data *)host->hostdata)->ncb; + return ((struct sym_data *)host->hostdata)->ncb; } #include "sym_fw.h" diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 13fd5b2..5d2079f 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -2760,8 +2760,9 @@ reset_all: * Use at your own decision and risk. */ -void sym_interrupt (struct sym_hcb *np) +irqreturn_t sym_interrupt(struct Scsi_Host *shost) { + struct sym_hcb *np = sym_get_hcb(shost); u_char istat, istatc; u_char dstat; u_short sist; @@ -2786,7 +2787,7 @@ void sym_interrupt (struct sym_hcb *np) } if (!(istat & (SIP|DIP))) - return; + return (istat & INTF) ? IRQ_HANDLED : IRQ_NONE; #if 0 /* We should never get this one */ if (istat & CABRT) @@ -2818,7 +2819,7 @@ void sym_interrupt (struct sym_hcb *np) * never clear. */ if (unlikely(sist == 0xffff && dstat == 0xff)) { if (pci_channel_offline(np->s.device)) - return; + return IRQ_NONE; } } while (istatc & (SIP|DIP)); @@ -2856,7 +2857,7 @@ void sym_interrupt (struct sym_hcb *np) else if (dstat & SIR) sym_int_sir(np); else if (dstat & SSI) OUTONB_STD(); else goto unknown_int; - return; + return IRQ_HANDLED; } /* @@ -2873,7 +2874,7 @@ void sym_interrupt (struct sym_hcb *np) if (sist & RST) { printf("%s: SCSI BUS reset detected.\n", sym_name(np)); sym_start_up (np, 1); - return; + return IRQ_HANDLED; } OUTB(np, nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */ @@ -2885,7 +2886,7 @@ void sym_interrupt (struct sym_hcb *np) else if (sist & STO) sym_int_sto (np); else if (sist & UDC) sym_int_udc (np); else goto unknown_int; - return; + return IRQ_HANDLED; } /* @@ -2900,7 +2901,7 @@ void sym_interrupt (struct sym_hcb *np) if ((sist & (GEN|HTH|SGE)) || (dstat & (MDPE|BF|ABRT|IID))) { sym_start_reset(np); - return; + return IRQ_HANDLED; } unknown_int: @@ -2911,6 +2912,7 @@ unknown_int: printf( "%s: unknown interrupt(s) ignored, " "ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n", sym_name(np), istat, dstat, sist); + return IRQ_NONE; } /* diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index 4354571..a9c0866 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -1056,7 +1056,7 @@ void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn); void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp); #endif void sym_start_up(struct sym_hcb *np, int reason); -void sym_interrupt(struct sym_hcb *np); +irqreturn_t sym_interrupt(struct Scsi_Host *); int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task); struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order); void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp); -- cgit v0.10.2 From 5111eefa17615bdf17ca00ec2cdca16302c7697e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:13 -0400 Subject: [SCSI] sym53c8xx: Remove pci_dev pointer from sym_shcb This structure is accessed by the device; the fewer Linux things in it, the better. Using the pci_dev pointer from the hostdata requires a lot of changes: - Pass Scsi_Host to a lot of routines which currently take a sym_hcb. - Set the Scsi_Host as the pci drvdata (instead of the sym_hcb) Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c index aa230d2..190770b 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.c +++ b/drivers/scsi/sym53c8xx_2/sym_fw.c @@ -104,8 +104,9 @@ static struct sym_fwz_ofs sym_fw2z_ofs = { * Patch routine for firmware #1. */ static void -sym_fw1_patch(struct sym_hcb *np) +sym_fw1_patch(struct Scsi_Host *shost) { + struct sym_hcb *np = sym_get_hcb(shost); struct sym_fw1a_scr *scripta0; struct sym_fw1b_scr *scriptb0; @@ -145,8 +146,11 @@ sym_fw1_patch(struct sym_hcb *np) * Patch routine for firmware #2. */ static void -sym_fw2_patch(struct sym_hcb *np) +sym_fw2_patch(struct Scsi_Host *shost) { + struct sym_data *sym_data = shost_priv(shost); + struct pci_dev *pdev = sym_data->pdev; + struct sym_hcb *np = sym_data->ncb; struct sym_fw2a_scr *scripta0; struct sym_fw2b_scr *scriptb0; @@ -205,14 +209,14 @@ sym_fw2_patch(struct sym_hcb *np) * Remove a couple of work-arounds specific to C1010 if * they are not desirable. See `sym_fw2.h' for more details. */ - if (!(np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_66 && - np->s.device->revision < 0x1 && + if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_66 && + pdev->revision < 0x1 && np->pciclk_khz < 60000)) { scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP); scripta0->datao_phase[1] = cpu_to_scr(0); } - if (!(np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_33 /* && - np->s.device->revision < 0xff */)) { + if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 /* && + pdev->revision < 0xff */)) { scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP); scripta0->sel_done[1] = cpu_to_scr(0); } diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.h b/drivers/scsi/sym53c8xx_2/sym_fw.h index 66ec35b..ae7e0f9 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.h +++ b/drivers/scsi/sym53c8xx_2/sym_fw.h @@ -143,7 +143,7 @@ struct sym_fw { *z_ofs; /* Useful offsets in script Z */ /* Setup and patch methods for this firmware */ void (*setup)(struct sym_hcb *, struct sym_fw *); - void (*patch)(struct sym_hcb *); + void (*patch)(struct Scsi_Host *); }; /* diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 1c18b3b..df0547a 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -497,14 +497,16 @@ static void sym_timer(struct sym_hcb *np) /* * PCI BUS error handler. */ -void sym_log_bus_error(struct sym_hcb *np) +void sym_log_bus_error(struct Scsi_Host *shost) { - u_short pci_sts; - pci_read_config_word(np->s.device, PCI_STATUS, &pci_sts); + struct sym_data *sym_data = shost_priv(shost); + struct pci_dev *pdev = sym_data->pdev; + unsigned short pci_sts; + pci_read_config_word(pdev, PCI_STATUS, &pci_sts); if (pci_sts & 0xf900) { - pci_write_config_word(np->s.device, PCI_STATUS, pci_sts); - printf("%s: PCI STATUS = 0x%04x\n", - sym_name(np), pci_sts & 0xf900); + pci_write_config_word(pdev, PCI_STATUS, pci_sts); + shost_printk(KERN_WARNING, shost, + "PCI bus error: status = 0x%04x\n", pci_sts & 0xf900); } } @@ -595,16 +597,17 @@ static void sym53c8xx_timer(unsigned long npref) */ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) { - struct sym_hcb *np = SYM_SOFTC_PTR(cmd); struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd); - struct Scsi_Host *host = cmd->device->host; - struct pci_dev *pdev = np->s.device; + struct Scsi_Host *shost = cmd->device->host; + struct sym_data *sym_data = shost_priv(shost); + struct pci_dev *pdev = sym_data->pdev; + struct sym_hcb *np = sym_data->ncb; SYM_QUEHEAD *qp; int cmd_queued = 0; int sts = -1; struct completion eh_done; - scmd_printk(KERN_WARNING, cmd, "%s operation started.\n", opname); + scmd_printk(KERN_WARNING, cmd, "%s operation started\n", opname); /* We may be in an error condition because the PCI bus * went down. In this case, we need to wait until the @@ -614,11 +617,10 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) */ #define WAIT_FOR_PCI_RECOVERY 35 if (pci_channel_offline(pdev)) { - struct sym_data *sym_data = shost_priv(host); struct completion *io_reset; int finished_reset = 0; init_completion(&eh_done); - spin_lock_irq(host->host_lock); + spin_lock_irq(shost->host_lock); /* Make sure we didn't race */ if (pci_channel_offline(pdev)) { if (!sym_data->io_reset) @@ -627,7 +629,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) } else { finished_reset = 1; } - spin_unlock_irq(host->host_lock); + spin_unlock_irq(shost->host_lock); if (!finished_reset) finished_reset = wait_for_completion_timeout(io_reset, WAIT_FOR_PCI_RECOVERY*HZ); @@ -635,7 +637,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) return SCSI_FAILED; } - spin_lock_irq(host->host_lock); + spin_lock_irq(shost->host_lock); /* This one is queued in some place -> to wait for completion */ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) { struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq); @@ -660,7 +662,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) break; case SYM_EH_HOST_RESET: sym_reset_scsi_bus(np, 0); - sym_start_up(np, 1); + sym_start_up(shost, 1); sts = 0; break; default: @@ -674,13 +676,13 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) if (cmd_queued) { init_completion(&eh_done); ucmd->eh_done = &eh_done; - spin_unlock_irq(host->host_lock); + spin_unlock_irq(shost->host_lock); if (!wait_for_completion_timeout(&eh_done, 5*HZ)) { ucmd->eh_done = NULL; sts = -2; } } else { - spin_unlock_irq(host->host_lock); + spin_unlock_irq(shost->host_lock); } dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname, @@ -993,8 +995,9 @@ static int is_keyword(char *ptr, int len, char *verb) * Parse a control command */ -static int sym_user_command(struct sym_hcb *np, char *buffer, int length) +static int sym_user_command(struct Scsi_Host *shost, char *buffer, int length) { + struct sym_hcb *np = sym_get_hcb(shost); char *ptr = buffer; int len = length; struct sym_usrcmd cmd, *uc = &cmd; @@ -1121,9 +1124,9 @@ printk("sym_user_command: data=%ld\n", uc->data); else { unsigned long flags; - spin_lock_irqsave(np->s.host->host_lock, flags); - sym_exec_user_command (np, uc); - spin_unlock_irqrestore(np->s.host->host_lock, flags); + spin_lock_irqsave(shost->host_lock, flags); + sym_exec_user_command(np, uc); + spin_unlock_irqrestore(shost->host_lock, flags); } return length; } @@ -1179,8 +1182,11 @@ static int copy_info(struct info_str *info, char *fmt, ...) /* * Copy formatted information into the input buffer. */ -static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len) +static int sym_host_info(struct Scsi_Host *shost, char *ptr, off_t offset, int len) { + struct sym_data *sym_data = shost_priv(shost); + struct pci_dev *pdev = sym_data->pdev; + struct sym_hcb *np = sym_data->ncb; struct info_str info; info.buffer = ptr; @@ -1190,9 +1196,9 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len) copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, " "revision id 0x%x\n", np->s.chip_name, - np->s.device->device, np->s.device->revision); + pdev->device, pdev->revision); copy_info(&info, "At PCI address %s, IRQ %u\n", - pci_name(np->s.device), np->s.device->irq); + pci_name(pdev), pdev->irq); copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n", (int) (np->minsync_dt ? np->minsync_dt : np->minsync), np->maxwide ? "Wide" : "Narrow", @@ -1211,15 +1217,14 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len) * - func = 0 means read (returns adapter infos) * - func = 1 means write (not yet merget from sym53c8xx) */ -static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer, +static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length, int func) { - struct sym_hcb *np = sym_get_hcb(host); int retv; if (func) { #ifdef SYM_LINUX_USER_COMMAND_SUPPORT - retv = sym_user_command(np, buffer, length); + retv = sym_user_command(shost, buffer, length); #else retv = -EINVAL; #endif @@ -1227,7 +1232,7 @@ static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer, if (start) *start = buffer; #ifdef SYM_LINUX_USER_INFO_SUPPORT - retv = sym_host_info(np, buffer, offset, length); + retv = sym_host_info(shost, buffer, offset, length); #else retv = -EINVAL; #endif @@ -1303,20 +1308,18 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, np = __sym_calloc_dma(&pdev->dev, sizeof(*np), "HCB"); if (!np) goto attach_failed; - np->s.device = pdev; np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */ sym_data->ncb = np; sym_data->pdev = pdev; np->s.host = shost; - pci_set_drvdata(pdev, np); + pci_set_drvdata(pdev, shost); /* * Copy some useful infos to the HCB. */ np->hcb_ba = vtobus(np); np->verbose = sym_driver_setup.verbose; - np->s.device = pdev; np->s.unit = unit; np->features = dev->chip.features; np->clock_divn = dev->chip.nr_divisor; @@ -1331,9 +1334,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, sprintf(np->s.inst_name, "sym%d", np->s.unit); if ((SYM_CONF_DMA_ADDRESSING_MODE > 0) && (np->features & FE_DAC) && - !pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) { + !pci_set_dma_mask(pdev, DMA_DAC_MASK)) { set_dac(np); - } else if (pci_set_dma_mask(np->s.device, DMA_32BIT_MASK)) { + } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printf_warning("%s: No suitable DMA available\n", sym_name(np)); goto attach_failed; } @@ -1380,7 +1383,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, /* * Start the SCRIPTS. */ - sym_start_up(np, 1); + sym_start_up(shost, 1); /* * Start the timer daemon @@ -1645,8 +1648,9 @@ static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev) * Detach the host. * We have to free resources and halt the NCR chip. */ -static int sym_detach(struct sym_hcb *np, struct pci_dev *pdev) +static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev) { + struct sym_hcb *np = sym_get_hcb(shost); printk("%s: detaching ...\n", sym_name(np)); del_timer_sync(&np->s.timer); @@ -1750,14 +1754,11 @@ static int __devinit sym2_probe(struct pci_dev *pdev, static void __devexit sym2_remove(struct pci_dev *pdev) { - struct sym_hcb *np = pci_get_drvdata(pdev); - struct Scsi_Host *host = np->s.host; - - scsi_remove_host(host); - scsi_host_put(host); - - sym_detach(np, pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); + scsi_remove_host(shost); + scsi_host_put(shost); + sym_detach(shost, pdev); pci_release_regions(pdev); pci_disable_device(pdev); @@ -1791,9 +1792,9 @@ static pci_ers_result_t sym2_io_error_detected(struct pci_dev *pdev, */ static pci_ers_result_t sym2_io_slot_dump(struct pci_dev *pdev) { - struct sym_hcb *np = pci_get_drvdata(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); - sym_dump_registers(np); + sym_dump_registers(shost); /* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET; @@ -1833,7 +1834,8 @@ static void sym2_reset_workarounds(struct pci_dev *pdev) */ static pci_ers_result_t sym2_io_slot_reset(struct pci_dev *pdev) { - struct sym_hcb *np = pci_get_drvdata(pdev); + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct sym_hcb *np = sym_get_hcb(shost); printk(KERN_INFO "%s: recovering from a PCI slot reset\n", sym_name(np)); @@ -1863,7 +1865,7 @@ static pci_ers_result_t sym2_io_slot_reset(struct pci_dev *pdev) sym_name(np)); return PCI_ERS_RESULT_DISCONNECT; } - sym_start_up(np, 1); + sym_start_up(shost, 1); } return PCI_ERS_RESULT_RECOVERED; @@ -1879,8 +1881,7 @@ static pci_ers_result_t sym2_io_slot_reset(struct pci_dev *pdev) */ static void sym2_io_resume(struct pci_dev *pdev) { - struct sym_hcb *np = pci_get_drvdata(pdev); - struct Scsi_Host *shost = np->s.host; + struct Scsi_Host *shost = pci_get_drvdata(pdev); struct sym_data *sym_data = shost_priv(shost); spin_lock_irq(shost->host_lock); diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index 98261a5..e5bd0af 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -179,7 +179,6 @@ struct sym_shcb { int unit; char inst_name[16]; char chip_name[8]; - struct pci_dev *device; struct Scsi_Host *host; @@ -266,7 +265,7 @@ void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb); void sym_xpt_async_bus_reset(struct sym_hcb *np); void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target); int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp); -void sym_log_bus_error(struct sym_hcb *np); -void sym_dump_registers(struct sym_hcb *np); +void sym_log_bus_error(struct Scsi_Host *); +void sym_dump_registers(struct Scsi_Host *); #endif /* SYM_GLUE_H */ diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 5d2079f..3cf1209 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -684,6 +684,8 @@ static void sym_set_bus_mode(struct sym_hcb *np, struct sym_nvram *nvram) */ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram) { + struct sym_data *sym_data = shost_priv(shost); + struct pci_dev *pdev = sym_data->pdev; u_char burst_max; u32 period; int i; @@ -797,8 +799,8 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru * In dual channel mode, contention occurs if internal cycles * are used. Disable internal cycles. */ - if (np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_33 && - np->s.device->revision < 0x1) + if (pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 && + pdev->revision < 0x1) np->rv_ccntl0 |= DILS; /* @@ -821,10 +823,10 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru * this driver. The generic ncr driver that does not use * LOAD/STORE instructions does not need this work-around. */ - if ((np->s.device->device == PCI_DEVICE_ID_NCR_53C810 && - np->s.device->revision >= 0x10 && np->s.device->revision <= 0x11) || - (np->s.device->device == PCI_DEVICE_ID_NCR_53C860 && - np->s.device->revision <= 0x1)) + if ((pdev->device == PCI_DEVICE_ID_NCR_53C810 && + pdev->revision >= 0x10 && pdev->revision <= 0x11) || + (pdev->device == PCI_DEVICE_ID_NCR_53C860 && + pdev->revision <= 0x1)) np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP); /* @@ -890,7 +892,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru if ((SYM_SETUP_SCSI_LED || (nvram->type == SYM_SYMBIOS_NVRAM || (nvram->type == SYM_TEKRAM_NVRAM && - np->s.device->device == PCI_DEVICE_ID_NCR_53C895))) && + pdev->device == PCI_DEVICE_ID_NCR_53C895))) && !(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01)) np->features |= FE_LED0; @@ -1128,8 +1130,9 @@ restart_test: * First 24 register of the chip: * r0..rf */ -static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat) +static void sym_log_hard_error(struct Scsi_Host *shost, u_short sist, u_char dstat) { + struct sym_hcb *np = sym_get_hcb(shost); u32 dsp; int script_ofs; int script_size; @@ -1182,17 +1185,18 @@ static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat) * PCI BUS error. */ if (dstat & (MDPE|BF)) - sym_log_bus_error(np); + sym_log_bus_error(shost); } -void sym_dump_registers(struct sym_hcb *np) +void sym_dump_registers(struct Scsi_Host *shost) { + struct sym_hcb *np = sym_get_hcb(shost); u_short sist; u_char dstat; sist = INW(np, nc_sist); dstat = INB(np, nc_dstat); - sym_log_hard_error(np, sist, dstat); + sym_log_hard_error(shost, sist, dstat); } static struct sym_chip sym_dev_table[] = { @@ -1700,8 +1704,11 @@ static void sym_flush_busy_queue (struct sym_hcb *np, int cam_status) * 1: SCSI BUS RESET delivered or received. * 2: SCSI BUS MODE changed. */ -void sym_start_up (struct sym_hcb *np, int reason) +void sym_start_up(struct Scsi_Host *shost, int reason) { + struct sym_data *sym_data = shost_priv(shost); + struct pci_dev *pdev = sym_data->pdev; + struct sym_hcb *np = sym_data->ncb; int i; u32 phys; @@ -1750,7 +1757,7 @@ void sym_start_up (struct sym_hcb *np, int reason) * This also let point to first position the start * and done queue pointers used from SCRIPTS. */ - np->fw_patch(np); + np->fw_patch(shost); /* * Wakeup all pending jobs. @@ -1792,7 +1799,7 @@ void sym_start_up (struct sym_hcb *np, int reason) /* * For now, disable AIP generation on C1010-66. */ - if (np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_66) + if (pdev->device == PCI_DEVICE_ID_LSI_53C1010_66) OUTB(np, nc_aipcntl1, DISAIP); /* @@ -1802,8 +1809,8 @@ void sym_start_up (struct sym_hcb *np, int reason) * that from SCRIPTS for each selection/reselection, but * I just don't want. :) */ - if (np->s.device->device == PCI_DEVICE_ID_LSI_53C1010_33 && - np->s.device->revision < 1) + if (pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 && + pdev->revision < 1) OUTB(np, nc_stest1, INB(np, nc_stest1) | 0x30); /* @@ -1811,9 +1818,9 @@ void sym_start_up (struct sym_hcb *np, int reason) * Disable overlapped arbitration for some dual function devices, * regardless revision id (kind of post-chip-design feature. ;-)) */ - if (np->s.device->device == PCI_DEVICE_ID_NCR_53C875) + if (pdev->device == PCI_DEVICE_ID_NCR_53C875) OUTB(np, nc_ctest0, (1<<5)); - else if (np->s.device->device == PCI_DEVICE_ID_NCR_53C896) + else if (pdev->device == PCI_DEVICE_ID_NCR_53C896) np->rv_ccntl0 |= DPR; /* @@ -2218,8 +2225,9 @@ static void sym_int_udc (struct sym_hcb *np) * mode to eight bit asynchronous, etc... * So, just reinitializing all except chip should be enough. */ -static void sym_int_sbmc (struct sym_hcb *np) +static void sym_int_sbmc(struct Scsi_Host *shost) { + struct sym_hcb *np = sym_get_hcb(shost); u_char scsi_mode = INB(np, nc_stest4) & SMODE; /* @@ -2232,7 +2240,7 @@ static void sym_int_sbmc (struct sym_hcb *np) * Should suspend command processing for a few seconds and * reinitialize all except the chip. */ - sym_start_up (np, 2); + sym_start_up(shost, 2); } /* @@ -2762,7 +2770,9 @@ reset_all: irqreturn_t sym_interrupt(struct Scsi_Host *shost) { - struct sym_hcb *np = sym_get_hcb(shost); + struct sym_data *sym_data = shost_priv(shost); + struct sym_hcb *np = sym_data->ncb; + struct pci_dev *pdev = sym_data->pdev; u_char istat, istatc; u_char dstat; u_short sist; @@ -2818,7 +2828,7 @@ irqreturn_t sym_interrupt(struct Scsi_Host *shost) /* Prevent deadlock waiting on a condition that may * never clear. */ if (unlikely(sist == 0xffff && dstat == 0xff)) { - if (pci_channel_offline(np->s.device)) + if (pci_channel_offline(pdev)) return IRQ_NONE; } } while (istatc & (SIP|DIP)); @@ -2873,7 +2883,7 @@ irqreturn_t sym_interrupt(struct Scsi_Host *shost) */ if (sist & RST) { printf("%s: SCSI BUS reset detected.\n", sym_name(np)); - sym_start_up (np, 1); + sym_start_up(shost, 1); return IRQ_HANDLED; } @@ -2882,7 +2892,7 @@ irqreturn_t sym_interrupt(struct Scsi_Host *shost) if (!(sist & (GEN|HTH|SGE)) && !(dstat & (MDPE|BF|ABRT|IID))) { - if (sist & SBMC) sym_int_sbmc (np); + if (sist & SBMC) sym_int_sbmc(shost); else if (sist & STO) sym_int_sto (np); else if (sist & UDC) sym_int_udc (np); else goto unknown_int; @@ -2896,7 +2906,7 @@ irqreturn_t sym_interrupt(struct Scsi_Host *shost) * Reset everything. */ - sym_log_hard_error(np, sist, dstat); + sym_log_hard_error(shost, sist, dstat); if ((sist & (GEN|HTH|SGE)) || (dstat & (MDPE|BF|ABRT|IID))) { diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index a9c0866..ad07880 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -909,7 +909,7 @@ struct sym_hcb { struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */ struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */ void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw); - void (*fw_patch)(struct sym_hcb *np); + void (*fw_patch)(struct Scsi_Host *); char *fw_name; /* @@ -1055,7 +1055,7 @@ void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn); #else void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp); #endif -void sym_start_up(struct sym_hcb *np, int reason); +void sym_start_up(struct Scsi_Host *, int reason); irqreturn_t sym_interrupt(struct Scsi_Host *); int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task); struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order); -- cgit v0.10.2 From aac6a5a34050a97016290f341e8de0a09f3a8f8c Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 5 Oct 2007 15:55:14 -0400 Subject: [SCSI] sym53c8xx: Remove sym_xpt_async_sent_bdr This function just printed a message to the user; move the print to its only caller, and turn it into an starget_printk. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index df0547a..0f74aba 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -163,14 +163,6 @@ void sym_xpt_async_bus_reset(struct sym_hcb *np) } /* - * Tell the SCSI layer about a BUS DEVICE RESET message sent. - */ -void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target) -{ - printf_notice("%s: TARGET %d has been reset.\n", sym_name(np), target); -} - -/* * Choose the more appropriate CAM status if * the IO encountered an extended error. */ diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index e5bd0af..567fbe0 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -263,7 +263,6 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid) void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb); #define sym_print_addr(cmd, arg...) dev_info(&cmd->device->sdev_gendev , ## arg) void sym_xpt_async_bus_reset(struct sym_hcb *np); -void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target); int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp); void sym_log_bus_error(struct Scsi_Host *); void sym_dump_registers(struct Scsi_Host *); diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 3cf1209..463f119 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -3543,7 +3543,8 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num) * If we sent a BDR, make upper layer aware of that. */ if (np->abrt_msg[0] == M_RESET) - sym_xpt_async_sent_bdr(np, target); + starget_printk(KERN_NOTICE, starget, + "has been reset\n"); break; } -- cgit v0.10.2 From 6557f3a06a5eb73b34d01b23523a513f2c52cadb Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 19 Oct 2007 15:59:13 -0700 Subject: [SCSI] qla2xxx: Resync with latest HBA SSID specification -- 2.2u. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_devtbl.h b/drivers/scsi/qla2xxx/qla_devtbl.h index dd43541..d78d35e 100644 --- a/drivers/scsi/qla2xxx/qla_devtbl.h +++ b/drivers/scsi/qla2xxx/qla_devtbl.h @@ -1,4 +1,4 @@ -#define QLA_MODEL_NAMES 0x57 +#define QLA_MODEL_NAMES 0x5C /* * Adapter model names and descriptions. @@ -91,4 +91,9 @@ static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = { " ", " ", /* 0x154 */ "QLE220", "PCI-Express to 4Gb FC, Single Channel", /* 0x155 */ "QLE220", "PCI-Express to 4Gb FC, Single Channel", /* 0x156 */ + " ", " ", /* 0x157 */ + " ", " ", /* 0x158 */ + " ", " ", /* 0x159 */ + " ", " ", /* 0x15a */ + "QME2472", "Dell BS PCI-Express to 4Gb FC, Dual Channel", /* 0x15b */ }; -- cgit v0.10.2 From a3a63d55a4eec418d845a91222ac53443f62717b Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 19 Oct 2007 15:59:14 -0700 Subject: [SCSI] qla2xxx: Defer explicit interrupt-polling processing to init-time scenarios. As the intermixing may cause issues where HCCR bits could be cleared inappropriately during MSI/MSI-X interrupt handling. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 7f6a89b..024c662 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -525,7 +525,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha) /* Check for pending interrupts. */ /* During init we issue marker directly */ - if (!ha->marker_needed) + if (!ha->marker_needed && !ha->flags.init_done) qla2x00_poll(ha); spin_lock_irq(&ha->hardware_lock); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index c53ec67..ccd662a 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -252,7 +252,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) /* Clean up */ ha->mcp = NULL; - if (!abort_active) { + if (abort_active || !io_lock_on) { DEBUG11(printk("%s(%ld): checking for additional resp " "interrupt.\n", __func__, ha->host_no)); -- cgit v0.10.2 From 2c96d8d0c17978bbf5eb82314d488f46d4a51280 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 19 Oct 2007 15:59:15 -0700 Subject: [SCSI] qla2xxx: Handle unaligned sector writes during NVRAM/VPD updates. Since both NVRAM and VPD regions of the flash reside on unaligned sector boundaries, during update, the driver must perform a read-modify-write operation to the composite NVRAM/VPD region. This affects ISP25xx type boards only. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 05fa779..2f0bd5a 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -114,7 +114,6 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, { struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); - unsigned long flags; uint16_t cnt; if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size) @@ -144,11 +143,9 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, } /* Write NVRAM. */ - spin_lock_irqsave(&ha->hardware_lock, flags); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base, count); - spin_unlock_irqrestore(&ha->hardware_lock, flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); @@ -397,16 +394,13 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, { struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); - unsigned long flags; if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size) return 0; /* Write NVRAM. */ - spin_lock_irqsave(&ha->hardware_lock, flags); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count); - spin_unlock_irqrestore(&ha->hardware_lock, flags); return count; } diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 6670ad5..c24f3d9 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -7,6 +7,7 @@ #include "qla_def.h" #include +#include #include static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t); @@ -745,9 +746,11 @@ qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, int ret, stat; uint32_t i; uint16_t *wptr; + unsigned long flags; ret = QLA_SUCCESS; + spin_lock_irqsave(&ha->hardware_lock, flags); qla2x00_lock_nvram_access(ha); /* Disable NVRAM write-protection. */ @@ -764,6 +767,7 @@ qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, qla2x00_set_nvram_protection(ha, stat); qla2x00_unlock_nvram_access(ha); + spin_unlock_irqrestore(&ha->hardware_lock, flags); return ret; } @@ -776,9 +780,11 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, uint32_t i; uint32_t *dwptr; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + unsigned long flags; ret = QLA_SUCCESS; + spin_lock_irqsave(&ha->hardware_lock, flags); /* Enable flash write. */ WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); @@ -812,6 +818,7 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ + spin_unlock_irqrestore(&ha->hardware_lock, flags); return ret; } @@ -836,8 +843,20 @@ int qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, uint32_t bytes) { - return qla24xx_write_flash_data(ha, (uint32_t *)buf, - FA_VPD_NVRAM_ADDR | naddr, bytes >> 2); +#define RMW_BUFFER_SIZE (64 * 1024) + uint8_t *dbuf; + + dbuf = vmalloc(RMW_BUFFER_SIZE); + if (!dbuf) + return QLA_MEMORY_ALLOC_FAILED; + ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, + RMW_BUFFER_SIZE); + memcpy(dbuf + (naddr << 2), buf, bytes); + ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, + RMW_BUFFER_SIZE); + vfree(dbuf); + + return QLA_SUCCESS; } static inline void -- cgit v0.10.2 From 94d6a2b32864421467d48f9a3a1c7b1da1e1dadf Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 19 Oct 2007 15:59:16 -0700 Subject: [SCSI] qla2xxx: Fix issue where final flash-segment updates were falling into the slow-path write handler. Original implementation would not use the burst-write mechanisms for requests equal to OPTROM_BURST_DWORDS transfer dwords. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index c24f3d9..ad2fa01 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -643,7 +643,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, } /* Go with burst-write. */ - if (optrom && (liter + OPTROM_BURST_DWORDS) < dwords) { + if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) { /* Copy data to DMA'ble buffer. */ for (miter = 0, s = optrom, d = dwptr; miter < OPTROM_BURST_DWORDS; miter++, s++, d++) -- cgit v0.10.2 From 285d0321d15cf3130b3347a207ceae652ccc95b5 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 19 Oct 2007 15:59:17 -0700 Subject: [SCSI] qla2xxx: Make driver (mostly) legacy I/O port free. Recent ISPs need only the single MMIO BAR to manipulate HW registers. Unfortunately, ISP21xx, ISP22xx, ISP23xx, and ISP63xx type cards still require the I/O mapped region to manipulate the FLASH via the two HW flash-registers (flash_address and flash_data). Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 1900fbf..04e8cbc 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2271,6 +2271,7 @@ typedef struct scsi_qla_host { spinlock_t hardware_lock ____cacheline_aligned; + int bars; device_reg_t __iomem *iobase; /* Base I/O address */ unsigned long pio_address; unsigned long pio_length; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 0351d38..a5bcf1f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1482,6 +1482,17 @@ qla2x00_iospace_config(scsi_qla_host_t *ha) unsigned long pio, pio_len, pio_flags; unsigned long mmio, mmio_len, mmio_flags; + if (pci_request_selected_regions(ha->pdev, ha->bars, + QLA2XXX_DRIVER_NAME)) { + qla_printk(KERN_WARNING, ha, + "Failed to reserve PIO/MMIO regions (%s)\n", + pci_name(ha->pdev)); + + goto iospace_error_exit; + } + if (!(ha->bars & 1)) + goto skip_pio; + /* We only need PIO for Flash operations on ISP2312 v2 chips. */ pio = pci_resource_start(ha->pdev, 0); pio_len = pci_resource_len(ha->pdev, 0); @@ -1499,7 +1510,10 @@ qla2x00_iospace_config(scsi_qla_host_t *ha) pci_name(ha->pdev)); pio = 0; } + ha->pio_address = pio; + ha->pio_length = pio_len; +skip_pio: /* Use MMIO operations for all accesses. */ mmio = pci_resource_start(ha->pdev, 1); mmio_len = pci_resource_len(ha->pdev, 1); @@ -1518,16 +1532,6 @@ qla2x00_iospace_config(scsi_qla_host_t *ha) goto iospace_error_exit; } - if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) { - qla_printk(KERN_WARNING, ha, - "Failed to reserve PIO/MMIO regions (%s)\n", - pci_name(ha->pdev)); - - goto iospace_error_exit; - } - - ha->pio_address = pio; - ha->pio_length = pio_len; ha->iobase = ioremap(mmio, MIN_IOBASE_LEN); if (!ha->iobase) { qla_printk(KERN_ERR, ha, @@ -1579,21 +1583,26 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) char pci_info[30]; char fw_str[30]; struct scsi_host_template *sht; + int bars; - if (pci_enable_device(pdev)) - goto probe_out; - - if (pci_find_aer_capability(pdev)) - if (pci_enable_pcie_error_reporting(pdev)) - goto probe_out; - + bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO); sht = &qla2x00_driver_template; if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 || - pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) { + bars = pci_select_bars(pdev, IORESOURCE_MEM); sht = &qla24xx_driver_template; + } + + if (pci_enable_device_bars(pdev, bars)) + goto probe_out; + + if (pci_find_aer_capability(pdev)) + if (pci_enable_pcie_error_reporting(pdev)) + goto probe_out; + host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t)); if (host == NULL) { printk(KERN_WARNING @@ -1610,6 +1619,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->host_no = host->host_no; sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no); ha->parent = NULL; + ha->bars = bars; /* Set ISP-type information. */ qla2x00_set_isp_flags(ha); @@ -1880,7 +1890,7 @@ qla2x00_free_device(scsi_qla_host_t *ha) /* release io space registers */ if (ha->iobase) iounmap(ha->iobase); - pci_release_regions(ha->pdev); + pci_release_selected_regions(ha->pdev, ha->bars); } static inline void @@ -2890,7 +2900,7 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev) pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; scsi_qla_host_t *ha = pci_get_drvdata(pdev); - if (pci_enable_device(pdev)) { + if (pci_enable_device_bars(pdev, ha->bars)) { qla_printk(KERN_WARNING, ha, "Can't re-enable PCI device after reset.\n"); -- cgit v0.10.2 From 6acf8190025e9c4ea513d4084ff089d476112816 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 19 Oct 2007 15:59:18 -0700 Subject: [SCSI] qla2xxx: Correct residual-count handling discrepancies during UNDERRUN handling. For recent ISPs, software during CS_UNDERRUN handling must determine if the two residuals, firmware-calculated and FCP_RSP, are different to recognize if a frame has been dropped. Update the driver to catch this condition, and clear the SS_RESIDUAL_UNDER and lscsi_status bits. This logic is consistent with what earlier firmwares did by explicitly cracking open the FCP_RSP statuses and clearing SS_RESIDUAL_UNDER. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index c4768c4..1104bd2 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1012,8 +1012,14 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) case CS_DATA_UNDERRUN: resid = resid_len; /* Use F/W calculated residual length. */ - if (IS_FWI2_CAPABLE(ha)) + if (IS_FWI2_CAPABLE(ha)) { + if (scsi_status & SS_RESIDUAL_UNDER && + resid != fw_resid_len) { + scsi_status &= ~SS_RESIDUAL_UNDER; + lscsi_status = 0; + } resid = fw_resid_len; + } if (scsi_status & SS_RESIDUAL_UNDER) { scsi_set_resid(cp, resid); -- cgit v0.10.2 From 8b7afc2a90d93d87d53732a9281c22facebe8d62 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 19 Oct 2007 15:59:19 -0700 Subject: [SCSI] qla2xxx: Correct display of ISP serial-number. The original serial-number calculations based on WWPN no longer apply to newer ISPs (ISP24xx and ISP25xx). These newer board's serial number reside in the VPD. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 2f0bd5a..fb388b8 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -538,6 +538,9 @@ qla2x00_serial_num_show(struct class_device *cdev, char *buf) scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); uint32_t sn; + if (IS_FWI2_CAPABLE(ha)) + return snprintf(buf, PAGE_SIZE, "\n"); + sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000, sn % 100000); -- cgit v0.10.2 From af2709fd0d127cd590e7a77ab50b23cdb9f6f48f Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 19 Oct 2007 15:59:20 -0700 Subject: [SCSI] qla2xxx: Update version number to 8.02.00-k5. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 2d551a3..ae6f7a2 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.00-k4" +#define QLA2XXX_VERSION "8.02.00-k5" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 -- cgit v0.10.2