Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (74 commits)
  [SCSI] sg: fix q->queue_lock on scsi_error_handler path
  [SCSI] replace __inline with inline
  [SCSI] a2091: make 2 functions static
  [SCSI] a3000: make 2 functions static
  [SCSI] ses: #if 0 the unused ses_match_host()
  [SCSI] use kmem_cache_zalloc instead of kmem_cache_alloc/memset
  [SCSI] sg: fix iovec bugs introduced by the block layer conversion
  [SCSI] qlogicpti: use request_firmware
  [SCSI] advansys: use request_firmware
  [SCSI] qla1280: use request_firmware
  [SCSI] libiscsi: fix iscsi pool error path
  [SCSI] cxgb3i: call ddp release function directly
  [SCSI] cxgb3i: merge cxgb3i_ddp into cxgb3i module
  [SCSI] cxgb3i: close all tcp connections upon chip reset
  [SCSI] cxgb3i: re-read ddp settings information after chip reset
  [SCSI] cxgb3i: re-initialize ddp settings after chip reset
  [SCSI] cxgb3i: subscribe to error notification from cxgb3 driver
  [SCSI] aacraid driver update
  [SCSI] mptsas: remove unneeded check
  [SCSI] config: Make need for SCSI_CDROM clearer
  ...
This commit is contained in:
Linus Torvalds 2009-04-06 13:24:49 -07:00
commit 22eb5aa6c7
88 changed files with 14192 additions and 12471 deletions

View file

@ -60,17 +60,9 @@ Supported Cards/Chipsets
9005:0285:9005:02d5 Adaptec ASR-2405 (Voodoo40 Lite)
9005:0285:9005:02d6 Adaptec ASR-2445 (Voodoo44 Lite)
9005:0285:9005:02d7 Adaptec ASR-2805 (Voodoo80 Lite)
9005:0285:9005:02d8 Adaptec 5405G (Voodoo40 PM)
9005:0285:9005:02d9 Adaptec 5445G (Voodoo44 PM)
9005:0285:9005:02da Adaptec 5805G (Voodoo80 PM)
9005:0285:9005:02db Adaptec 5085G (Voodoo08 PM)
9005:0285:9005:02dc Adaptec 51245G (Voodoo124 PM)
9005:0285:9005:02dd Adaptec 51645G (Voodoo164 PM)
9005:0285:9005:02de Adaptec 52445G (Voodoo244 PM)
9005:0285:9005:02df Adaptec ASR-2045G (Voodoo04 Lite PM)
9005:0285:9005:02e0 Adaptec ASR-2405G (Voodoo40 Lite PM)
9005:0285:9005:02e1 Adaptec ASR-2445G (Voodoo44 Lite PM)
9005:0285:9005:02e2 Adaptec ASR-2805G (Voodoo80 Lite PM)
9005:0285:9005:02d8 Adaptec 5405Z (Voodoo40 BLBU)
9005:0285:9005:02d9 Adaptec 5445Z (Voodoo44 BLBU)
9005:0285:9005:02da Adaptec 5805Z (Voodoo80 BLBU)
1011:0046:9005:0364 Adaptec 5400S (Mustang)
1011:0046:9005:0365 Adaptec 5400S (Mustang)
9005:0287:9005:0800 Adaptec Themisto (Jupiter)
@ -140,6 +132,7 @@ Deanna Bonds (non-DASD support, PAE fibs and 64 bit,
where fibs that go to the hardware are consistently called hw_fibs and
not just fibs like the name of the driver tracking structure)
Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
Achim Leubner <Achim_Leubner@adaptec.com>
Original Driver
-------------------------

View file

@ -2279,9 +2279,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
if (port_info->phy_info &&
(!(port_info->phy_info[0].identify.device_info &
MPI_SAS_DEVICE_INFO_SMP_TARGET)))
if (!(port_info->phy_info[0].identify.device_info &
MPI_SAS_DEVICE_INFO_SMP_TARGET))
continue;
if (mptsas_sas_expander_pg0(ioc, &buffer,

View file

@ -121,10 +121,11 @@ config BLK_DEV_SR
tristate "SCSI CDROM support"
depends on SCSI
---help---
If you want to use a SCSI or FireWire CD-ROM under Linux,
say Y and read the SCSI-HOWTO and the CDROM-HOWTO at
<http://www.tldp.org/docs.html#howto>. Also make sure to say
Y or M to "ISO 9660 CD-ROM file system support" later.
If you want to use a CD or DVD drive attached to your computer
by SCSI, FireWire, USB or ATAPI, say Y and read the SCSI-HOWTO
and the CDROM-HOWTO at <http://www.tldp.org/docs.html#howto>.
Make sure to say Y or M to "ISO 9660 CD-ROM file system support".
To compile this driver as a module, choose M here and read
<file:Documentation/scsi/scsi.txt>.
@ -614,10 +615,16 @@ config LIBFC
---help---
Fibre Channel library module
config LIBFCOE
tristate "LibFCoE module"
select LIBFC
---help---
Library for Fibre Channel over Ethernet module
config FCOE
tristate "FCoE module"
depends on PCI
select LIBFC
select LIBFCOE
---help---
Fibre Channel over Ethernet module

View file

@ -37,6 +37,7 @@ obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o
obj-$(CONFIG_SCSI_DH) += device_handler/
obj-$(CONFIG_LIBFC) += libfc/
obj-$(CONFIG_LIBFCOE) += fcoe/
obj-$(CONFIG_FCOE) += fcoe/
obj-$(CONFIG_ISCSI_TCP) += libiscsi.o libiscsi_tcp.o iscsi_tcp.o
obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o

View file

@ -23,6 +23,8 @@
#define DMA(ptr) ((a2091_scsiregs *)((ptr)->base))
#define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
static int a2091_release(struct Scsi_Host *instance);
static irqreturn_t a2091_intr (int irq, void *_instance)
{
unsigned long flags;
@ -144,7 +146,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
}
}
int __init a2091_detect(struct scsi_host_template *tpnt)
static int __init a2091_detect(struct scsi_host_template *tpnt)
{
static unsigned char called = 0;
struct Scsi_Host *instance;
@ -233,7 +235,7 @@ static struct scsi_host_template driver_template = {
#include "scsi_module.c"
int a2091_release(struct Scsi_Host *instance)
static int a2091_release(struct Scsi_Host *instance)
{
#ifdef MODULE
DMA(instance)->CNTR = 0;

View file

@ -11,9 +11,6 @@
#include <linux/types.h>
int a2091_detect(struct scsi_host_template *);
int a2091_release(struct Scsi_Host *);
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
#endif

View file

@ -25,6 +25,8 @@
static struct Scsi_Host *a3000_host = NULL;
static int a3000_release(struct Scsi_Host *instance);
static irqreturn_t a3000_intr (int irq, void *dummy)
{
unsigned long flags;
@ -157,7 +159,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
}
}
int __init a3000_detect(struct scsi_host_template *tpnt)
static int __init a3000_detect(struct scsi_host_template *tpnt)
{
wd33c93_regs regs;
@ -232,7 +234,7 @@ static struct scsi_host_template driver_template = {
#include "scsi_module.c"
int a3000_release(struct Scsi_Host *instance)
static int a3000_release(struct Scsi_Host *instance)
{
wd33c93_release();
DMA(instance)->CNTR = 0;

View file

@ -11,9 +11,6 @@
#include <linux/types.h>
int a3000_detect(struct scsi_host_template *);
int a3000_release(struct Scsi_Host *);
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
#endif

View file

@ -143,7 +143,7 @@ static char *aac_get_status_string(u32 status);
*/
static int nondasd = -1;
static int aac_cache;
static int aac_cache = 2; /* WCE=0 to avoid performance problems */
static int dacmode = -1;
int aac_msi;
int aac_commit = -1;
@ -157,7 +157,7 @@ module_param_named(cache, aac_cache, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(cache, "Disable Queue Flush commands:\n"
"\tbit 0 - Disable FUA in WRITE SCSI commands\n"
"\tbit 1 - Disable SYNCHRONIZE_CACHE SCSI command\n"
"\tbit 2 - Disable only if Battery not protecting Cache");
"\tbit 2 - Disable only if Battery is protecting Cache");
module_param(dacmode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC."
" 0=off, 1=on");
@ -217,6 +217,14 @@ int aac_reset_devices;
module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization.");
int aac_wwn = 1;
module_param_named(wwn, aac_wwn, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(wwn, "Select a WWN type for the arrays:\n"
"\t0 - Disable\n"
"\t1 - Array Meta Data Signature (default)\n"
"\t2 - Adapter Serial Number");
static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
struct fib *fibptr) {
struct scsi_device *device;
@ -1206,9 +1214,8 @@ static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd)
static int aac_scsi_32_64(struct fib * fib, struct scsi_cmnd * cmd)
{
if ((sizeof(dma_addr_t) > 4) &&
(num_physpages > (0xFFFFFFFFULL >> PAGE_SHIFT)) &&
(fib->dev->adapter_info.options & AAC_OPT_SGMAP_HOST64))
if ((sizeof(dma_addr_t) > 4) && fib->dev->needs_dac &&
(fib->dev->adapter_info.options & AAC_OPT_SGMAP_HOST64))
return FAILED;
return aac_scsi_32(fib, cmd);
}
@ -1371,8 +1378,11 @@ int aac_get_adapter_info(struct aac_dev* dev)
if (dev->nondasd_support && !dev->in_reset)
printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id);
if (dma_get_required_mask(&dev->pdev->dev) > DMA_32BIT_MASK)
dev->needs_dac = 1;
dev->dac_support = 0;
if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){
if ((sizeof(dma_addr_t) > 4) && dev->needs_dac &&
(dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)) {
if (!dev->in_reset)
printk(KERN_INFO "%s%d: 64bit support enabled.\n",
dev->name, dev->id);
@ -1382,6 +1392,15 @@ int aac_get_adapter_info(struct aac_dev* dev)
if(dacmode != -1) {
dev->dac_support = (dacmode!=0);
}
/* avoid problems with AAC_QUIRK_SCSI_32 controllers */
if (dev->dac_support && (aac_get_driver_ident(dev->cardtype)->quirks
& AAC_QUIRK_SCSI_32)) {
dev->nondasd_support = 0;
dev->jbod = 0;
expose_physicals = 0;
}
if(dev->dac_support != 0) {
if (!pci_set_dma_mask(dev->pdev, DMA_64BIT_MASK) &&
!pci_set_consistent_dma_mask(dev->pdev, DMA_64BIT_MASK)) {
@ -2058,7 +2077,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));
memset(&inq_data, 0, sizeof (struct inquiry_data));
if (scsicmd->cmnd[1] & 0x1) {
if ((scsicmd->cmnd[1] & 0x1) && aac_wwn) {
char *arr = (char *)&inq_data;
/* EVPD bit set */
@ -2081,7 +2100,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
arr[1] = scsicmd->cmnd[2];
scsi_sg_copy_from_buffer(scsicmd, &inq_data,
sizeof(inq_data));
return aac_get_container_serial(scsicmd);
if (aac_wwn != 2)
return aac_get_container_serial(
scsicmd);
/* SLES 10 SP1 special */
scsicmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
} else {
/* vpd page not implemented */
scsicmd->result = DID_OK << 16 |

View file

@ -12,7 +12,7 @@
*----------------------------------------------------------------------------*/
#ifndef AAC_DRIVER_BUILD
# define AAC_DRIVER_BUILD 2456
# define AAC_DRIVER_BUILD 2461
# define AAC_DRIVER_BRANCH "-ms"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
@ -865,7 +865,11 @@ struct aac_supplement_adapter_info
u8 MfgPcbaSerialNo[12];
u8 MfgWWNName[8];
__le32 SupportedOptions2;
__le32 ReservedGrowth[1];
__le32 StructExpansion;
/* StructExpansion == 1 */
__le32 FeatureBits3;
__le32 SupportedPerformanceModes;
__le32 ReservedForFutureGrowth[80];
};
#define AAC_FEATURE_FALCON cpu_to_le32(0x00000010)
#define AAC_FEATURE_JBOD cpu_to_le32(0x08000000)
@ -1020,6 +1024,7 @@ struct aac_dev
u8 jbod;
u8 cache_protected;
u8 dac_support;
u8 needs_dac;
u8 raid_scsi_mode;
u8 comm_interface;
# define AAC_COMM_PRODUCER 0

View file

@ -54,6 +54,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
const unsigned long printfbufsiz = 256;
struct aac_init *init;
dma_addr_t phys;
unsigned long aac_max_hostphysmempages;
size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz;
@ -90,7 +91,18 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys);
init->AdapterFibsSize = cpu_to_le32(fibsize);
init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
/*
* number of 4k pages of host physical memory. The aacraid fw needs
* this number to be less than 4gb worth of pages. New firmware doesn't
* have any issues with the mapping system, but older Firmware did, and
* had *troubles* dealing with the math overloading past 32 bits, thus
* we must limit this field.
*/
aac_max_hostphysmempages = dma_get_required_mask(&dev->pdev->dev) >> 12;
if (aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES)
init->HostPhysMemPages = cpu_to_le32(aac_max_hostphysmempages);
else
init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
init->InitFlags = 0;
if (dev->comm_interface == AAC_COMM_MESSAGE) {

View file

@ -86,7 +86,13 @@ char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
*
* Note: The last field is used to index into aac_drivers below.
*/
static struct pci_device_id aac_pci_tbl[] = {
#ifdef DECLARE_PCI_DEVICE_TABLE
static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = {
#elif defined(__devinitconst)
static const struct pci_device_id aac_pci_tbl[] __devinitconst = {
#else
static const struct pci_device_id aac_pci_tbl[] __devinitdata = {
#endif
{ 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */
{ 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */
{ 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */

File diff suppressed because it is too large Load diff

View file

@ -1034,7 +1034,7 @@ ahd_intr(struct ahd_softc *ahd)
}
/******************************** Private Inlines *****************************/
static __inline void
static inline void
ahd_assert_atn(struct ahd_softc *ahd)
{
ahd_outb(ahd, SCSISIGO, ATNO);
@ -1069,7 +1069,7 @@ ahd_currently_packetized(struct ahd_softc *ahd)
return (packetized);
}
static __inline int
static inline int
ahd_set_active_fifo(struct ahd_softc *ahd)
{
u_int active_fifo;
@ -1086,7 +1086,7 @@ ahd_set_active_fifo(struct ahd_softc *ahd)
}
}
static __inline void
static inline void
ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl)
{
ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL);
@ -1096,7 +1096,7 @@ ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl)
* Determine whether the sequencer reported a residual
* for this SCB/transaction.
*/
static __inline void
static inline void
ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)
{
uint32_t sgptr;
@ -1106,7 +1106,7 @@ ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)
ahd_calc_residual(ahd, scb);
}
static __inline void
static inline void
ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb)
{
uint32_t sgptr;
@ -7987,7 +7987,7 @@ ahd_resume(struct ahd_softc *ahd)
* scbid that should be restored once manipualtion
* of the TCL entry is complete.
*/
static __inline u_int
static inline u_int
ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl)
{
/*

View file

@ -46,21 +46,20 @@
#define _AIC79XX_INLINE_H_
/******************************** Debugging ***********************************/
static __inline char *ahd_name(struct ahd_softc *ahd);
static inline char *ahd_name(struct ahd_softc *ahd);
static __inline char *
ahd_name(struct ahd_softc *ahd)
static inline char *ahd_name(struct ahd_softc *ahd)
{
return (ahd->name);
}
/************************ Sequencer Execution Control *************************/
static __inline void ahd_known_modes(struct ahd_softc *ahd,
static inline void ahd_known_modes(struct ahd_softc *ahd,
ahd_mode src, ahd_mode dst);
static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
static inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
ahd_mode src,
ahd_mode dst);
static __inline void ahd_extract_mode_state(struct ahd_softc *ahd,
static inline void ahd_extract_mode_state(struct ahd_softc *ahd,
ahd_mode_state state,
ahd_mode *src, ahd_mode *dst);
@ -73,7 +72,7 @@ int ahd_is_paused(struct ahd_softc *ahd);
void ahd_pause(struct ahd_softc *ahd);
void ahd_unpause(struct ahd_softc *ahd);
static __inline void
static inline void
ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
{
ahd->src_mode = src;
@ -82,13 +81,13 @@ ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
ahd->saved_dst_mode = dst;
}
static __inline ahd_mode_state
static inline ahd_mode_state
ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
{
return ((src << SRC_MODE_SHIFT) | (dst << DST_MODE_SHIFT));
}
static __inline void
static inline void
ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state,
ahd_mode *src, ahd_mode *dst)
{
@ -102,13 +101,12 @@ void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
bus_size_t len, int last);
/************************** Memory mapping routines ***************************/
static __inline size_t ahd_sg_size(struct ahd_softc *ahd);
static inline size_t ahd_sg_size(struct ahd_softc *ahd);
void ahd_sync_sglist(struct ahd_softc *ahd,
struct scb *scb, int op);
static __inline size_t
ahd_sg_size(struct ahd_softc *ahd)
static inline size_t ahd_sg_size(struct ahd_softc *ahd)
{
if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
return (sizeof(struct ahd_dma64_seg));
@ -141,11 +139,9 @@ struct scb *
ahd_lookup_scb(struct ahd_softc *ahd, u_int tag);
void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
static __inline uint8_t *
ahd_get_sense_buf(struct ahd_softc *ahd,
static inline uint8_t *ahd_get_sense_buf(struct ahd_softc *ahd,
struct scb *scb);
static __inline uint32_t
ahd_get_sense_bufaddr(struct ahd_softc *ahd,
static inline uint32_t ahd_get_sense_bufaddr(struct ahd_softc *ahd,
struct scb *scb);
#if 0 /* unused */
@ -158,13 +154,13 @@ do { \
#endif
static __inline uint8_t *
static inline uint8_t *
ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
{
return (scb->sense_data);
}
static __inline uint32_t
static inline uint32_t
ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
{
return (scb->sense_busaddr);

View file

@ -395,19 +395,19 @@ struct info_str {
};
/******************************** Locking *************************************/
static __inline void
static inline void
ahd_lockinit(struct ahd_softc *ahd)
{
spin_lock_init(&ahd->platform_data->spin_lock);
}
static __inline void
static inline void
ahd_lock(struct ahd_softc *ahd, unsigned long *flags)
{
spin_lock_irqsave(&ahd->platform_data->spin_lock, *flags);
}
static __inline void
static inline void
ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
{
spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
@ -490,29 +490,29 @@ void ahd_pci_write_config(ahd_dev_softc_t pci,
int reg, uint32_t value,
int width);
static __inline int ahd_get_pci_function(ahd_dev_softc_t);
static __inline int
static inline int ahd_get_pci_function(ahd_dev_softc_t);
static inline int
ahd_get_pci_function(ahd_dev_softc_t pci)
{
return (PCI_FUNC(pci->devfn));
}
static __inline int ahd_get_pci_slot(ahd_dev_softc_t);
static __inline int
static inline int ahd_get_pci_slot(ahd_dev_softc_t);
static inline int
ahd_get_pci_slot(ahd_dev_softc_t pci)
{
return (PCI_SLOT(pci->devfn));
}
static __inline int ahd_get_pci_bus(ahd_dev_softc_t);
static __inline int
static inline int ahd_get_pci_bus(ahd_dev_softc_t);
static inline int
ahd_get_pci_bus(ahd_dev_softc_t pci)
{
return (pci->bus->number);
}
static __inline void ahd_flush_device_writes(struct ahd_softc *);
static __inline void
static inline void ahd_flush_device_writes(struct ahd_softc *);
static inline void
ahd_flush_device_writes(struct ahd_softc *ahd)
{
/* XXX Is this sufficient for all architectures??? */
@ -524,81 +524,81 @@ int ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
off_t, int, int);
/*********************** Transaction Access Wrappers **************************/
static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahd_get_transaction_status(struct scb *);
static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahd_get_scsi_status(struct scb *);
static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
static __inline u_long ahd_get_transfer_length(struct scb *);
static __inline int ahd_get_transfer_dir(struct scb *);
static __inline void ahd_set_residual(struct scb *, u_long);
static __inline void ahd_set_sense_residual(struct scb *scb, u_long resid);
static __inline u_long ahd_get_residual(struct scb *);
static __inline u_long ahd_get_sense_residual(struct scb *);
static __inline int ahd_perform_autosense(struct scb *);
static __inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *,
static inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
static inline void ahd_set_transaction_status(struct scb *, uint32_t);
static inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
static inline void ahd_set_scsi_status(struct scb *, uint32_t);
static inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
static inline uint32_t ahd_get_transaction_status(struct scb *);
static inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
static inline uint32_t ahd_get_scsi_status(struct scb *);
static inline void ahd_set_transaction_tag(struct scb *, int, u_int);
static inline u_long ahd_get_transfer_length(struct scb *);
static inline int ahd_get_transfer_dir(struct scb *);
static inline void ahd_set_residual(struct scb *, u_long);
static inline void ahd_set_sense_residual(struct scb *scb, u_long resid);
static inline u_long ahd_get_residual(struct scb *);
static inline u_long ahd_get_sense_residual(struct scb *);
static inline int ahd_perform_autosense(struct scb *);
static inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *,
struct scb *);
static __inline void ahd_notify_xfer_settings_change(struct ahd_softc *,
static inline void ahd_notify_xfer_settings_change(struct ahd_softc *,
struct ahd_devinfo *);
static __inline void ahd_platform_scb_free(struct ahd_softc *ahd,
static inline void ahd_platform_scb_free(struct ahd_softc *ahd,
struct scb *scb);
static __inline void ahd_freeze_scb(struct scb *scb);
static inline void ahd_freeze_scb(struct scb *scb);
static __inline
static inline
void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~(CAM_STATUS_MASK << 16);
cmd->result |= status << 16;
}
static __inline
static inline
void ahd_set_transaction_status(struct scb *scb, uint32_t status)
{
ahd_cmd_set_transaction_status(scb->io_ctx,status);
}
static __inline
static inline
void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~0xFFFF;
cmd->result |= status;
}
static __inline
static inline
void ahd_set_scsi_status(struct scb *scb, uint32_t status)
{
ahd_cmd_set_scsi_status(scb->io_ctx, status);
}
static __inline
static inline
uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
{
return ((cmd->result >> 16) & CAM_STATUS_MASK);
}
static __inline
static inline
uint32_t ahd_get_transaction_status(struct scb *scb)
{
return (ahd_cmd_get_transaction_status(scb->io_ctx));
}
static __inline
static inline
uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
{
return (cmd->result & 0xFFFF);
}
static __inline
static inline
uint32_t ahd_get_scsi_status(struct scb *scb)
{
return (ahd_cmd_get_scsi_status(scb->io_ctx));
}
static __inline
static inline
void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type)
{
/*
@ -607,43 +607,43 @@ void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type)
*/
}
static __inline
static inline
u_long ahd_get_transfer_length(struct scb *scb)
{
return (scb->platform_data->xfer_len);
}
static __inline
static inline
int ahd_get_transfer_dir(struct scb *scb)
{
return (scb->io_ctx->sc_data_direction);
}
static __inline
static inline
void ahd_set_residual(struct scb *scb, u_long resid)
{
scsi_set_resid(scb->io_ctx, resid);
}
static __inline
static inline
void ahd_set_sense_residual(struct scb *scb, u_long resid)
{
scb->platform_data->sense_resid = resid;
}
static __inline
static inline
u_long ahd_get_residual(struct scb *scb)
{
return scsi_get_resid(scb->io_ctx);
}
static __inline
static inline
u_long ahd_get_sense_residual(struct scb *scb)
{
return (scb->platform_data->sense_resid);
}
static __inline
static inline
int ahd_perform_autosense(struct scb *scb)
{
/*
@ -654,20 +654,20 @@ int ahd_perform_autosense(struct scb *scb)
return (1);
}
static __inline uint32_t
static inline uint32_t
ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb)
{
return (sizeof(struct scsi_sense_data));
}
static __inline void
static inline void
ahd_notify_xfer_settings_change(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo)
{
/* Nothing to do here for linux */
}
static __inline void
static inline void
ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
{
ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
@ -678,7 +678,7 @@ void ahd_platform_free(struct ahd_softc *ahd);
void ahd_platform_init(struct ahd_softc *ahd);
void ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb);
static __inline void
static inline void
ahd_freeze_scb(struct scb *scb)
{
if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {

View file

@ -51,7 +51,7 @@
#include "aic79xx_pci.h"
static __inline uint64_t
static inline uint64_t
ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
{
uint64_t id;
@ -377,14 +377,12 @@ ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)
error = ahd_init(ahd);
if (error != 0)
return (error);
ahd->init_level++;
/*
* Allow interrupts now that we are completely setup.
*/
error = ahd_pci_map_int(ahd);
if (!error)
ahd->init_level++;
return error;
return ahd_pci_map_int(ahd);
}
#ifdef CONFIG_PM

View file

@ -55,10 +55,9 @@ void ahc_sync_sglist(struct ahc_softc *ahc,
struct scb *scb, int op);
/******************************** Debugging ***********************************/
static __inline char *ahc_name(struct ahc_softc *ahc);
static inline char *ahc_name(struct ahc_softc *ahc);
static __inline char *
ahc_name(struct ahc_softc *ahc)
static inline char *ahc_name(struct ahc_softc *ahc)
{
return (ahc->name);
}

View file

@ -230,7 +230,7 @@ int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t);
#include "aic7xxx.h"
/***************************** Timer Facilities *******************************/
static __inline void
static inline void
ahc_scb_timer_reset(struct scb *scb, u_int usec)
{
}
@ -401,19 +401,19 @@ struct info_str {
/******************************** Locking *************************************/
/* Lock protecting internal data structures */
static __inline void
static inline void
ahc_lockinit(struct ahc_softc *ahc)
{
spin_lock_init(&ahc->platform_data->spin_lock);
}
static __inline void
static inline void
ahc_lock(struct ahc_softc *ahc, unsigned long *flags)
{
spin_lock_irqsave(&ahc->platform_data->spin_lock, *flags);
}
static __inline void
static inline void
ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
{
spin_unlock_irqrestore(&ahc->platform_data->spin_lock, *flags);
@ -493,22 +493,22 @@ void ahc_pci_write_config(ahc_dev_softc_t pci,
int reg, uint32_t value,
int width);
static __inline int ahc_get_pci_function(ahc_dev_softc_t);
static __inline int
static inline int ahc_get_pci_function(ahc_dev_softc_t);
static inline int
ahc_get_pci_function(ahc_dev_softc_t pci)
{
return (PCI_FUNC(pci->devfn));
}
static __inline int ahc_get_pci_slot(ahc_dev_softc_t);
static __inline int
static inline int ahc_get_pci_slot(ahc_dev_softc_t);
static inline int
ahc_get_pci_slot(ahc_dev_softc_t pci)
{
return (PCI_SLOT(pci->devfn));
}
static __inline int ahc_get_pci_bus(ahc_dev_softc_t);
static __inline int
static inline int ahc_get_pci_bus(ahc_dev_softc_t);
static inline int
ahc_get_pci_bus(ahc_dev_softc_t pci)
{
return (pci->bus->number);
@ -521,8 +521,8 @@ static inline void ahc_linux_pci_exit(void) {
}
#endif
static __inline void ahc_flush_device_writes(struct ahc_softc *);
static __inline void
static inline void ahc_flush_device_writes(struct ahc_softc *);
static inline void
ahc_flush_device_writes(struct ahc_softc *ahc)
{
/* XXX Is this sufficient for all architectures??? */
@ -535,81 +535,81 @@ int ahc_linux_proc_info(struct Scsi_Host *, char *, char **,
/*************************** Domain Validation ********************************/
/*********************** Transaction Access Wrappers *************************/
static __inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
static __inline void ahc_set_transaction_status(struct scb *, uint32_t);
static __inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
static __inline void ahc_set_scsi_status(struct scb *, uint32_t);
static __inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahc_get_transaction_status(struct scb *);
static __inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahc_get_scsi_status(struct scb *);
static __inline void ahc_set_transaction_tag(struct scb *, int, u_int);
static __inline u_long ahc_get_transfer_length(struct scb *);
static __inline int ahc_get_transfer_dir(struct scb *);
static __inline void ahc_set_residual(struct scb *, u_long);
static __inline void ahc_set_sense_residual(struct scb *scb, u_long resid);
static __inline u_long ahc_get_residual(struct scb *);
static __inline u_long ahc_get_sense_residual(struct scb *);
static __inline int ahc_perform_autosense(struct scb *);
static __inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *,
static inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
static inline void ahc_set_transaction_status(struct scb *, uint32_t);
static inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
static inline void ahc_set_scsi_status(struct scb *, uint32_t);
static inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd);
static inline uint32_t ahc_get_transaction_status(struct scb *);
static inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd);
static inline uint32_t ahc_get_scsi_status(struct scb *);
static inline void ahc_set_transaction_tag(struct scb *, int, u_int);
static inline u_long ahc_get_transfer_length(struct scb *);
static inline int ahc_get_transfer_dir(struct scb *);
static inline void ahc_set_residual(struct scb *, u_long);
static inline void ahc_set_sense_residual(struct scb *scb, u_long resid);
static inline u_long ahc_get_residual(struct scb *);
static inline u_long ahc_get_sense_residual(struct scb *);
static inline int ahc_perform_autosense(struct scb *);
static inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *,
struct scb *);
static __inline void ahc_notify_xfer_settings_change(struct ahc_softc *,
static inline void ahc_notify_xfer_settings_change(struct ahc_softc *,
struct ahc_devinfo *);
static __inline void ahc_platform_scb_free(struct ahc_softc *ahc,
static inline void ahc_platform_scb_free(struct ahc_softc *ahc,
struct scb *scb);
static __inline void ahc_freeze_scb(struct scb *scb);
static inline void ahc_freeze_scb(struct scb *scb);
static __inline
static inline
void ahc_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~(CAM_STATUS_MASK << 16);
cmd->result |= status << 16;
}
static __inline
static inline
void ahc_set_transaction_status(struct scb *scb, uint32_t status)
{
ahc_cmd_set_transaction_status(scb->io_ctx,status);
}
static __inline
static inline
void ahc_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~0xFFFF;
cmd->result |= status;
}
static __inline
static inline
void ahc_set_scsi_status(struct scb *scb, uint32_t status)
{
ahc_cmd_set_scsi_status(scb->io_ctx, status);
}
static __inline
static inline
uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd)
{
return ((cmd->result >> 16) & CAM_STATUS_MASK);
}
static __inline
static inline
uint32_t ahc_get_transaction_status(struct scb *scb)
{
return (ahc_cmd_get_transaction_status(scb->io_ctx));
}
static __inline
static inline
uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd)
{
return (cmd->result & 0xFFFF);
}
static __inline
static inline
uint32_t ahc_get_scsi_status(struct scb *scb)
{
return (ahc_cmd_get_scsi_status(scb->io_ctx));
}
static __inline
static inline
void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type)
{
/*
@ -618,43 +618,43 @@ void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type)
*/
}
static __inline
static inline
u_long ahc_get_transfer_length(struct scb *scb)
{
return (scb->platform_data->xfer_len);
}
static __inline
static inline
int ahc_get_transfer_dir(struct scb *scb)
{
return (scb->io_ctx->sc_data_direction);
}
static __inline
static inline
void ahc_set_residual(struct scb *scb, u_long resid)
{
scsi_set_resid(scb->io_ctx, resid);
}
static __inline
static inline
void ahc_set_sense_residual(struct scb *scb, u_long resid)
{
scb->platform_data->sense_resid = resid;
}
static __inline
static inline
u_long ahc_get_residual(struct scb *scb)
{
return scsi_get_resid(scb->io_ctx);
}
static __inline
static inline
u_long ahc_get_sense_residual(struct scb *scb)
{
return (scb->platform_data->sense_resid);
}
static __inline
static inline
int ahc_perform_autosense(struct scb *scb)
{
/*
@ -665,20 +665,20 @@ int ahc_perform_autosense(struct scb *scb)
return (1);
}
static __inline uint32_t
static inline uint32_t
ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb)
{
return (sizeof(struct scsi_sense_data));
}
static __inline void
static inline void
ahc_notify_xfer_settings_change(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo)
{
/* Nothing to do here for linux */
}
static __inline void
static inline void
ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb)
{
}
@ -687,7 +687,7 @@ int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
void ahc_platform_free(struct ahc_softc *ahc);
void ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
static __inline void
static inline void
ahc_freeze_scb(struct scb *scb)
{
if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {

View file

@ -54,7 +54,7 @@
#include "aic7xxx_pci.h"
static __inline uint64_t
static inline uint64_t
ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
{
uint64_t id;
@ -960,16 +960,12 @@ ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry)
error = ahc_init(ahc);
if (error != 0)
return (error);
ahc->init_level++;
/*
* Allow interrupts now that we are completely setup.
*/
error = ahc_pci_map_int(ahc);
if (error != 0)
return (error);
ahc->init_level++;
return (0);
return ahc_pci_map_int(ahc);
}
/*

View file

@ -133,7 +133,7 @@ struct scsi_sense_data
#define SCSI_STATUS_TASK_ABORTED 0x40
/************************* Large Disk Handling ********************************/
static __inline int
static inline int
aic_sector_div(sector_t capacity, int heads, int sectors)
{
/* ugly, ugly sector_div calling convention.. */
@ -141,7 +141,7 @@ aic_sector_div(sector_t capacity, int heads, int sectors)
return (int)capacity;
}
static __inline uint32_t
static inline uint32_t
scsi_4btoul(uint8_t *bytes)
{
uint32_t rv;

View file

@ -1,4 +1,4 @@
EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3
cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i_ddp.o cxgb3i.o
cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o
obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o

View file

@ -66,10 +66,12 @@ struct cxgb3i_hba {
* @pdev: pointer to pci dev
* @hba_cnt: # of hbas (the same as # of ports)
* @hba: all the hbas on this adapter
* @flags: bit flag for adapter event/status
* @tx_max_size: max. tx packet size supported
* @rx_max_size: max. rx packet size supported
* @tag_format: ddp tag format settings
*/
#define CXGB3I_ADAPTER_FLAG_RESET 0x1
struct cxgb3i_adapter {
struct list_head list_head;
spinlock_t lock;
@ -78,6 +80,7 @@ struct cxgb3i_adapter {
unsigned char hba_cnt;
struct cxgb3i_hba *hba[MAX_NPORTS];
unsigned int flags;
unsigned int tx_max_size;
unsigned int rx_max_size;
@ -137,10 +140,9 @@ struct cxgb3i_task_data {
int cxgb3i_iscsi_init(void);
void cxgb3i_iscsi_cleanup(void);
struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *);
void cxgb3i_adapter_remove(struct t3cdev *);
int cxgb3i_adapter_ulp_init(struct cxgb3i_adapter *);
void cxgb3i_adapter_ulp_cleanup(struct cxgb3i_adapter *);
struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *);
void cxgb3i_adapter_open(struct t3cdev *);
void cxgb3i_adapter_close(struct t3cdev *);
struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *);
struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *,

View file

@ -23,19 +23,6 @@
#include "cxgb3i_ddp.h"
#define DRV_MODULE_NAME "cxgb3i_ddp"
#define DRV_MODULE_VERSION "1.0.0"
#define DRV_MODULE_RELDATE "Dec. 1, 2008"
static char version[] =
"Chelsio S3xx iSCSI DDP " DRV_MODULE_NAME
" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Karen Xie <kxie@chelsio.com>");
MODULE_DESCRIPTION("cxgb3i ddp pagepod manager");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
#define ddp_log_error(fmt...) printk(KERN_ERR "cxgb3i_ddp: ERR! " fmt)
#define ddp_log_warn(fmt...) printk(KERN_WARNING "cxgb3i_ddp: WARN! " fmt)
#define ddp_log_info(fmt...) printk(KERN_INFO "cxgb3i_ddp: " fmt)
@ -66,9 +53,6 @@ static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
static unsigned char page_idx = DDP_PGIDX_MAX;
static LIST_HEAD(cxgb3i_ddp_list);
static DEFINE_RWLOCK(cxgb3i_ddp_rwlock);
/*
* functions to program the pagepod in h/w
*/
@ -113,8 +97,8 @@ static int set_ddp_map(struct cxgb3i_ddp_info *ddp, struct pagepod_hdr *hdr,
return 0;
}
static int clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int idx,
unsigned int npods)
static void clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int tag,
unsigned int idx, unsigned int npods)
{
unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
int i;
@ -122,13 +106,17 @@ static int clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int idx,
for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
struct sk_buff *skb = ddp->gl_skb[idx];
if (!skb) {
ddp_log_error("ddp tag 0x%x, 0x%x, %d/%u, skb NULL.\n",
tag, idx, i, npods);
continue;
}
ddp->gl_skb[idx] = NULL;
memset((skb->head + sizeof(struct ulp_mem_io)), 0, PPOD_SIZE);
ulp_mem_io_set_hdr(skb, pm_addr);
skb->priority = CPL_PRIORITY_CONTROL;
cxgb3_ofld_send(ddp->tdev, skb);
}
return 0;
}
static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp,
@ -211,7 +199,6 @@ int cxgb3i_ddp_find_page_index(unsigned long pgsz)
ddp_log_debug("ddp page size 0x%lx not supported.\n", pgsz);
return DDP_PGIDX_MAX;
}
EXPORT_SYMBOL_GPL(cxgb3i_ddp_find_page_index);
static inline void ddp_gl_unmap(struct pci_dev *pdev,
struct cxgb3i_gather_list *gl)
@ -334,7 +321,6 @@ error_out:
kfree(gl);
return NULL;
}
EXPORT_SYMBOL_GPL(cxgb3i_ddp_make_gl);
/**
* cxgb3i_ddp_release_gl - release a page buffer list
@ -348,7 +334,6 @@ void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
ddp_gl_unmap(pdev, gl);
kfree(gl);
}
EXPORT_SYMBOL_GPL(cxgb3i_ddp_release_gl);
/**
* cxgb3i_ddp_tag_reserve - set up ddp for a data transfer
@ -430,7 +415,6 @@ unmark_entries:
ddp_unmark_entries(ddp, idx, npods);
return err;
}
EXPORT_SYMBOL_GPL(cxgb3i_ddp_tag_reserve);
/**
* cxgb3i_ddp_tag_release - release a ddp tag
@ -453,22 +437,21 @@ void cxgb3i_ddp_tag_release(struct t3cdev *tdev, u32 tag)
struct cxgb3i_gather_list *gl = ddp->gl_map[idx];
unsigned int npods;
if (!gl) {
ddp_log_error("release ddp 0x%x, idx 0x%x, gl NULL.\n",
tag, idx);
if (!gl || !gl->nelem) {
ddp_log_error("release 0x%x, idx 0x%x, gl 0x%p, %u.\n",
tag, idx, gl, gl ? gl->nelem : 0);
return;
}
npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
ddp_log_debug("ddp tag 0x%x, release idx 0x%x, npods %u.\n",
tag, idx, npods);
clear_ddp_map(ddp, idx, npods);
clear_ddp_map(ddp, tag, idx, npods);
ddp_unmark_entries(ddp, idx, npods);
cxgb3i_ddp_release_gl(gl, ddp->pdev);
} else
ddp_log_error("ddp tag 0x%x, idx 0x%x > max 0x%x.\n",
tag, idx, ddp->nppods);
}
EXPORT_SYMBOL_GPL(cxgb3i_ddp_tag_release);
static int setup_conn_pgidx(struct t3cdev *tdev, unsigned int tid, int pg_idx,
int reply)
@ -509,7 +492,6 @@ int cxgb3i_setup_conn_host_pagesize(struct t3cdev *tdev, unsigned int tid,
{
return setup_conn_pgidx(tdev, tid, page_idx, reply);
}
EXPORT_SYMBOL_GPL(cxgb3i_setup_conn_host_pagesize);
/**
* cxgb3i_setup_conn_pagesize - setup the conn.'s ddp page size
@ -526,7 +508,6 @@ int cxgb3i_setup_conn_pagesize(struct t3cdev *tdev, unsigned int tid,
return setup_conn_pgidx(tdev, tid, pgidx, reply);
}
EXPORT_SYMBOL_GPL(cxgb3i_setup_conn_pagesize);
/**
* cxgb3i_setup_conn_digest - setup conn. digest setting
@ -562,26 +543,104 @@ int cxgb3i_setup_conn_digest(struct t3cdev *tdev, unsigned int tid,
cxgb3_ofld_send(tdev, skb);
return 0;
}
EXPORT_SYMBOL_GPL(cxgb3i_setup_conn_digest);
static int ddp_init(struct t3cdev *tdev)
/**
* cxgb3i_adapter_ddp_info - read the adapter's ddp information
* @tdev: t3cdev adapter
* @tformat: tag format
* @txsz: max tx pdu payload size, filled in by this func.
* @rxsz: max rx pdu payload size, filled in by this func.
* setup the tag format for a given iscsi entity
*/
int cxgb3i_adapter_ddp_info(struct t3cdev *tdev,
struct cxgb3i_tag_format *tformat,
unsigned int *txsz, unsigned int *rxsz)
{
struct cxgb3i_ddp_info *ddp;
unsigned char idx_bits;
if (!tformat)
return -EINVAL;
if (!tdev->ulp_iscsi)
return -EINVAL;
ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
idx_bits = 32 - tformat->sw_bits;
tformat->rsvd_bits = ddp->idx_bits;
tformat->rsvd_shift = PPOD_IDX_SHIFT;
tformat->rsvd_mask = (1 << tformat->rsvd_bits) - 1;
ddp_log_info("tag format: sw %u, rsvd %u,%u, mask 0x%x.\n",
tformat->sw_bits, tformat->rsvd_bits,
tformat->rsvd_shift, tformat->rsvd_mask);
*txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
*rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
ddp_log_info("max payload size: %u/%u, %u/%u.\n",
*txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz);
return 0;
}
/**
* cxgb3i_ddp_cleanup - release the cxgb3 adapter's ddp resource
* @tdev: t3cdev adapter
* release all the resource held by the ddp pagepod manager for a given
* adapter if needed
*/
void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
{
int i = 0;
struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp);
if (ddp) {
tdev->ulp_iscsi = NULL;
while (i < ddp->nppods) {
struct cxgb3i_gather_list *gl = ddp->gl_map[i];
if (gl) {
int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
>> PPOD_PAGES_SHIFT;
ddp_log_info("t3dev 0x%p, ddp %d + %d.\n",
tdev, i, npods);
kfree(gl);
ddp_free_gl_skb(ddp, i, npods);
i += npods;
} else
i++;
}
cxgb3i_free_big_mem(ddp);
}
}
/**
* ddp_init - initialize the cxgb3 adapter's ddp resource
* @tdev: t3cdev adapter
* initialize the ddp pagepod manager for a given adapter
*/
static void ddp_init(struct t3cdev *tdev)
{
struct cxgb3i_ddp_info *ddp;
struct ulp_iscsi_info uinfo;
unsigned int ppmax, bits;
int i, err;
static int vers_printed;
if (!vers_printed) {
printk(KERN_INFO "%s", version);
vers_printed = 1;
if (tdev->ulp_iscsi) {
ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
tdev, tdev->ulp_iscsi);
return;
}
err = tdev->ctl(tdev, ULP_ISCSI_GET_PARAMS, &uinfo);
if (err < 0) {
ddp_log_error("%s, failed to get iscsi param err=%d.\n",
tdev->name, err);
return err;
return;
}
ppmax = (uinfo.ulimit - uinfo.llimit + 1) >> PPOD_SIZE_SHIFT;
@ -598,7 +657,7 @@ static int ddp_init(struct t3cdev *tdev)
if (!ddp) {
ddp_log_warn("%s unable to alloc ddp 0x%d, ddp disabled.\n",
tdev->name, ppmax);
return 0;
return;
}
ddp->gl_map = (struct cxgb3i_gather_list **)(ddp + 1);
ddp->gl_skb = (struct sk_buff **)(((char *)ddp->gl_map) +
@ -632,142 +691,26 @@ static int ddp_init(struct t3cdev *tdev)
tdev->ulp_iscsi = ddp;
/* add to the list */
write_lock(&cxgb3i_ddp_rwlock);
list_add_tail(&ddp->list, &cxgb3i_ddp_list);
write_unlock(&cxgb3i_ddp_rwlock);
ddp_log_info("nppods %u (0x%x ~ 0x%x), bits %u, mask 0x%x,0x%x "
"pkt %u/%u, %u/%u.\n",
ppmax, ddp->llimit, ddp->ulimit, ddp->idx_bits,
ddp->idx_mask, ddp->rsvd_tag_mask,
ddp->max_txsz, uinfo.max_txsz,
ddp_log_info("tdev 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u,"
" %u/%u.\n",
tdev, ppmax, ddp->idx_bits, ddp->idx_mask,
ddp->rsvd_tag_mask, ddp->max_txsz, uinfo.max_txsz,
ddp->max_rxsz, uinfo.max_rxsz);
return 0;
return;
free_ddp_map:
cxgb3i_free_big_mem(ddp);
return err;
}
/**
* cxgb3i_adapter_ddp_init - initialize the adapter's ddp resource
* @tdev: t3cdev adapter
* @tformat: tag format
* @txsz: max tx pdu payload size, filled in by this func.
* @rxsz: max rx pdu payload size, filled in by this func.
* initialize the ddp pagepod manager for a given adapter if needed and
* setup the tag format for a given iscsi entity
* cxgb3i_ddp_init - initialize ddp functions
*/
int cxgb3i_adapter_ddp_init(struct t3cdev *tdev,
struct cxgb3i_tag_format *tformat,
unsigned int *txsz, unsigned int *rxsz)
void cxgb3i_ddp_init(struct t3cdev *tdev)
{
struct cxgb3i_ddp_info *ddp;
unsigned char idx_bits;
if (!tformat)
return -EINVAL;
if (!tdev->ulp_iscsi) {
int err = ddp_init(tdev);
if (err < 0)
return err;
if (page_idx == DDP_PGIDX_MAX) {
page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n",
PAGE_SIZE, page_idx);
}
ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
idx_bits = 32 - tformat->sw_bits;
tformat->rsvd_bits = ddp->idx_bits;
tformat->rsvd_shift = PPOD_IDX_SHIFT;
tformat->rsvd_mask = (1 << tformat->rsvd_bits) - 1;
ddp_log_info("tag format: sw %u, rsvd %u,%u, mask 0x%x.\n",
tformat->sw_bits, tformat->rsvd_bits,
tformat->rsvd_shift, tformat->rsvd_mask);
*txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
*rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
ddp_log_info("max payload size: %u/%u, %u/%u.\n",
*txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz);
return 0;
ddp_init(tdev);
}
EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_init);
static void ddp_release(struct cxgb3i_ddp_info *ddp)
{
int i = 0;
struct t3cdev *tdev = ddp->tdev;
tdev->ulp_iscsi = NULL;
while (i < ddp->nppods) {
struct cxgb3i_gather_list *gl = ddp->gl_map[i];
if (gl) {
int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
>> PPOD_PAGES_SHIFT;
kfree(gl);
ddp_free_gl_skb(ddp, i, npods);
} else
i++;
}
cxgb3i_free_big_mem(ddp);
}
/**
* cxgb3i_adapter_ddp_cleanup - release the adapter's ddp resource
* @tdev: t3cdev adapter
* release all the resource held by the ddp pagepod manager for a given
* adapter if needed
*/
void cxgb3i_adapter_ddp_cleanup(struct t3cdev *tdev)
{
struct cxgb3i_ddp_info *ddp;
/* remove from the list */
write_lock(&cxgb3i_ddp_rwlock);
list_for_each_entry(ddp, &cxgb3i_ddp_list, list) {
if (ddp->tdev == tdev) {
list_del(&ddp->list);
break;
}
}
write_unlock(&cxgb3i_ddp_rwlock);
if (ddp)
ddp_release(ddp);
}
EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_cleanup);
/**
* cxgb3i_ddp_init_module - module init entry point
* initialize any driver wide global data structures
*/
static int __init cxgb3i_ddp_init_module(void)
{
page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n",
PAGE_SIZE, page_idx);
return 0;
}
/**
* cxgb3i_ddp_exit_module - module cleanup/exit entry point
* go through the ddp list and release any resource held.
*/
static void __exit cxgb3i_ddp_exit_module(void)
{
struct cxgb3i_ddp_info *ddp;
/* release all ddp manager if there is any */
write_lock(&cxgb3i_ddp_rwlock);
list_for_each_entry(ddp, &cxgb3i_ddp_list, list) {
list_del(&ddp->list);
ddp_release(ddp);
}
write_unlock(&cxgb3i_ddp_rwlock);
}
module_init(cxgb3i_ddp_init_module);
module_exit(cxgb3i_ddp_exit_module);

View file

@ -301,7 +301,9 @@ int cxgb3i_setup_conn_pagesize(struct t3cdev *, unsigned int tid, int reply,
int cxgb3i_setup_conn_digest(struct t3cdev *, unsigned int tid,
int hcrc, int dcrc, int reply);
int cxgb3i_ddp_find_page_index(unsigned long pgsz);
int cxgb3i_adapter_ddp_init(struct t3cdev *, struct cxgb3i_tag_format *,
int cxgb3i_adapter_ddp_info(struct t3cdev *, struct cxgb3i_tag_format *,
unsigned int *txsz, unsigned int *rxsz);
void cxgb3i_adapter_ddp_cleanup(struct t3cdev *);
void cxgb3i_ddp_init(struct t3cdev *);
void cxgb3i_ddp_cleanup(struct t3cdev *);
#endif

View file

@ -12,8 +12,8 @@
#include "cxgb3i.h"
#define DRV_MODULE_NAME "cxgb3i"
#define DRV_MODULE_VERSION "1.0.1"
#define DRV_MODULE_RELDATE "Jan. 2009"
#define DRV_MODULE_VERSION "1.0.2"
#define DRV_MODULE_RELDATE "Mar. 2009"
static char version[] =
"Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME
@ -26,6 +26,7 @@ MODULE_VERSION(DRV_MODULE_VERSION);
static void open_s3_dev(struct t3cdev *);
static void close_s3_dev(struct t3cdev *);
static void s3_err_handler(struct t3cdev *tdev, u32 status, u32 error);
static cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
static struct cxgb3_client t3c_client = {
@ -33,6 +34,7 @@ static struct cxgb3_client t3c_client = {
.handlers = cxgb3i_cpl_handlers,
.add = open_s3_dev,
.remove = close_s3_dev,
.err_handler = s3_err_handler,
};
/**
@ -48,8 +50,9 @@ static void open_s3_dev(struct t3cdev *t3dev)
vers_printed = 1;
}
cxgb3i_ddp_init(t3dev);
cxgb3i_sdev_add(t3dev, &t3c_client);
cxgb3i_adapter_add(t3dev);
cxgb3i_adapter_open(t3dev);
}
/**
@ -58,8 +61,28 @@ static void open_s3_dev(struct t3cdev *t3dev)
*/
static void close_s3_dev(struct t3cdev *t3dev)
{
cxgb3i_adapter_remove(t3dev);
cxgb3i_adapter_close(t3dev);
cxgb3i_sdev_remove(t3dev);
cxgb3i_ddp_cleanup(t3dev);
}
static void s3_err_handler(struct t3cdev *tdev, u32 status, u32 error)
{
struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(tdev);
cxgb3i_log_info("snic 0x%p, tdev 0x%p, status 0x%x, err 0x%x.\n",
snic, tdev, status, error);
if (!snic)
return;
switch (status) {
case OFFLOAD_STATUS_DOWN:
snic->flags |= CXGB3I_ADAPTER_FLAG_RESET;
break;
case OFFLOAD_STATUS_UP:
snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
break;
}
}
/**

View file

@ -53,36 +53,52 @@ static LIST_HEAD(cxgb3i_snic_list);
static DEFINE_RWLOCK(cxgb3i_snic_rwlock);
/**
* cxgb3i_adapter_add - init a s3 adapter structure and any h/w settings
* @t3dev: t3cdev adapter
* return the resulting cxgb3i_adapter struct
* cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev
* @tdev: t3cdev pointer
*/
struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev)
struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev)
{
struct cxgb3i_adapter *snic;
struct adapter *adapter = tdev2adap(t3dev);
int i;
snic = kzalloc(sizeof(*snic), GFP_KERNEL);
if (!snic) {
cxgb3i_api_debug("cxgb3 %s, OOM.\n", t3dev->name);
return NULL;
read_lock(&cxgb3i_snic_rwlock);
list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
if (snic->tdev == tdev) {
read_unlock(&cxgb3i_snic_rwlock);
return snic;
}
}
spin_lock_init(&snic->lock);
read_unlock(&cxgb3i_snic_rwlock);
return NULL;
}
static inline int adapter_update(struct cxgb3i_adapter *snic)
{
cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n",
snic, snic->tdev);
return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format,
&snic->tx_max_size,
&snic->rx_max_size);
}
static int adapter_add(struct cxgb3i_adapter *snic)
{
struct t3cdev *t3dev = snic->tdev;
struct adapter *adapter = tdev2adap(t3dev);
int i, err;
snic->tdev = t3dev;
snic->pdev = adapter->pdev;
snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
if (cxgb3i_adapter_ddp_init(t3dev, &snic->tag_format,
err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format,
&snic->tx_max_size,
&snic->rx_max_size) < 0)
goto free_snic;
&snic->rx_max_size);
if (err < 0)
return err;
for_each_port(adapter, i) {
snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]);
if (!snic->hba[i])
goto ulp_cleanup;
return -EINVAL;
}
snic->hba_cnt = adapter->params.nports;
@ -91,46 +107,71 @@ struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev)
list_add_tail(&snic->list_head, &cxgb3i_snic_list);
write_unlock(&cxgb3i_snic_rwlock);
return snic;
ulp_cleanup:
cxgb3i_adapter_ddp_cleanup(t3dev);
free_snic:
kfree(snic);
return NULL;
cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n",
t3dev, snic, snic->hba_cnt);
return 0;
}
/**
* cxgb3i_adapter_remove - release the resources held and cleanup h/w settings
* cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
* @t3dev: t3cdev adapter
*/
void cxgb3i_adapter_remove(struct t3cdev *t3dev)
void cxgb3i_adapter_open(struct t3cdev *t3dev)
{
struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
int err;
if (snic)
err = adapter_update(snic);
else {
snic = kzalloc(sizeof(*snic), GFP_KERNEL);
if (snic) {
spin_lock_init(&snic->lock);
snic->tdev = t3dev;
err = adapter_add(snic);
} else
err = -ENOMEM;
}
if (err < 0) {
cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
snic, snic ? snic->flags : 0, t3dev, err);
if (snic) {
snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
cxgb3i_adapter_close(t3dev);
}
}
}
/**
* cxgb3i_adapter_close - release the resources held and cleanup h/w settings
* @t3dev: t3cdev adapter
*/
void cxgb3i_adapter_close(struct t3cdev *t3dev)
{
struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
int i;
struct cxgb3i_adapter *snic;
if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) {
cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n",
t3dev, snic, snic ? snic->flags : 0);
return;
}
/* remove from the list */
write_lock(&cxgb3i_snic_rwlock);
list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
if (snic->tdev == t3dev) {
list_del(&snic->list_head);
break;
}
}
list_del(&snic->list_head);
write_unlock(&cxgb3i_snic_rwlock);
if (snic) {
for (i = 0; i < snic->hba_cnt; i++) {
if (snic->hba[i]) {
cxgb3i_hba_host_remove(snic->hba[i]);
snic->hba[i] = NULL;
}
for (i = 0; i < snic->hba_cnt; i++) {
if (snic->hba[i]) {
cxgb3i_hba_host_remove(snic->hba[i]);
snic->hba[i] = NULL;
}
/* release ddp resources */
cxgb3i_adapter_ddp_cleanup(snic->tdev);
kfree(snic);
}
cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n",
t3dev, snic, snic->hba_cnt);
kfree(snic);
}
/**
@ -170,7 +211,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
shost = iscsi_host_alloc(&cxgb3i_host_template,
sizeof(struct cxgb3i_hba), 1);
if (!shost) {
cxgb3i_log_info("iscsi_host_alloc failed.\n");
cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n",
snic, ndev);
return NULL;
}
@ -188,7 +230,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
pci_dev_get(snic->pdev);
err = iscsi_host_add(shost, &snic->pdev->dev);
if (err) {
cxgb3i_log_info("iscsi_host_add failed.\n");
cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n",
snic, ndev);
goto pci_dev_put;
}

View file

@ -94,29 +94,30 @@ static int c3cn_get_port(struct s3_conn *c3cn, struct cxgb3i_sdev_data *cdata)
if (!cdata)
goto error_out;
if (c3cn->saddr.sin_port != 0) {
idx = ntohs(c3cn->saddr.sin_port) - cxgb3_sport_base;
if (idx < 0 || idx >= cxgb3_max_connect)
return 0;
if (!test_and_set_bit(idx, cdata->sport_map))
return -EADDRINUSE;
if (c3cn->saddr.sin_port) {
cxgb3i_log_error("connect, sin_port NON-ZERO %u.\n",
c3cn->saddr.sin_port);
return -EADDRINUSE;
}
/* the sport_map_next may not be accurate but that is okay, sport_map
should be */
start = idx = cdata->sport_map_next;
spin_lock_bh(&cdata->lock);
start = idx = cdata->sport_next;
do {
if (++idx >= cxgb3_max_connect)
idx = 0;
if (!(test_and_set_bit(idx, cdata->sport_map))) {
if (!cdata->sport_conn[idx]) {
c3cn->saddr.sin_port = htons(cxgb3_sport_base + idx);
cdata->sport_map_next = idx;
cdata->sport_next = idx;
cdata->sport_conn[idx] = c3cn;
spin_unlock_bh(&cdata->lock);
c3cn_conn_debug("%s reserve port %u.\n",
cdata->cdev->name,
cxgb3_sport_base + idx);
return 0;
}
} while (idx != start);
spin_unlock_bh(&cdata->lock);
error_out:
return -EADDRNOTAVAIL;
@ -124,15 +125,19 @@ error_out:
static void c3cn_put_port(struct s3_conn *c3cn)
{
struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(c3cn->cdev);
if (!c3cn->cdev)
return;
if (c3cn->saddr.sin_port) {
struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(c3cn->cdev);
int idx = ntohs(c3cn->saddr.sin_port) - cxgb3_sport_base;
c3cn->saddr.sin_port = 0;
if (idx < 0 || idx >= cxgb3_max_connect)
return;
clear_bit(idx, cdata->sport_map);
spin_lock_bh(&cdata->lock);
cdata->sport_conn[idx] = NULL;
spin_unlock_bh(&cdata->lock);
c3cn_conn_debug("%s, release port %u.\n",
cdata->cdev->name, cxgb3_sport_base + idx);
}
@ -1305,11 +1310,7 @@ static void c3cn_release_offload_resources(struct s3_conn *c3cn)
struct t3cdev *cdev = c3cn->cdev;
unsigned int tid = c3cn->tid;
if (!cdev)
return;
c3cn->qset = 0;
c3cn_free_cpl_skbs(c3cn);
if (c3cn->wr_avail != c3cn->wr_max) {
@ -1317,18 +1318,22 @@ static void c3cn_release_offload_resources(struct s3_conn *c3cn)
reset_wr_list(c3cn);
}
if (c3cn->l2t) {
l2t_release(L2DATA(cdev), c3cn->l2t);
c3cn->l2t = NULL;
}
if (c3cn->state == C3CN_STATE_CONNECTING) /* we have ATID */
s3_free_atid(cdev, tid);
else { /* we have TID */
cxgb3_remove_tid(cdev, (void *)c3cn, tid);
c3cn_put(c3cn);
if (cdev) {
if (c3cn->l2t) {
l2t_release(L2DATA(cdev), c3cn->l2t);
c3cn->l2t = NULL;
}
if (c3cn->state == C3CN_STATE_CONNECTING)
/* we have ATID */
s3_free_atid(cdev, tid);
else {
/* we have TID */
cxgb3_remove_tid(cdev, (void *)c3cn, tid);
c3cn_put(c3cn);
}
}
c3cn->dst_cache = NULL;
c3cn->cdev = NULL;
}
@ -1417,17 +1422,18 @@ static void c3cn_active_close(struct s3_conn *c3cn)
}
/**
* cxgb3i_c3cn_release - close and release an iscsi tcp connection
* cxgb3i_c3cn_release - close and release an iscsi tcp connection and any
* resource held
* @c3cn: the iscsi tcp connection
*/
void cxgb3i_c3cn_release(struct s3_conn *c3cn)
{
c3cn_conn_debug("c3cn 0x%p, s %u, f 0x%lx.\n",
c3cn, c3cn->state, c3cn->flags);
if (likely(c3cn->state != C3CN_STATE_CONNECTING))
c3cn_active_close(c3cn);
else
if (unlikely(c3cn->state == C3CN_STATE_CONNECTING))
c3cn_set_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED);
else if (likely(c3cn->state != C3CN_STATE_CLOSED))
c3cn_active_close(c3cn);
c3cn_put(c3cn);
}
@ -1656,7 +1662,6 @@ int cxgb3i_c3cn_connect(struct s3_conn *c3cn, struct sockaddr_in *usin)
c3cn_set_state(c3cn, C3CN_STATE_CLOSED);
ip_rt_put(rt);
c3cn_put_port(c3cn);
c3cn->daddr.sin_port = 0;
return err;
}
@ -1776,10 +1781,25 @@ out_err:
static void sdev_data_cleanup(struct cxgb3i_sdev_data *cdata)
{
struct adap_ports *ports = &cdata->ports;
struct s3_conn *c3cn;
int i;
for (i = 0; i < cxgb3_max_connect; i++) {
if (cdata->sport_conn[i]) {
c3cn = cdata->sport_conn[i];
cdata->sport_conn[i] = NULL;
spin_lock_bh(&c3cn->lock);
c3cn->cdev = NULL;
c3cn_set_flag(c3cn, C3CN_OFFLOAD_DOWN);
c3cn_closed(c3cn);
spin_unlock_bh(&c3cn->lock);
}
}
for (i = 0; i < ports->nports; i++)
NDEV2CDATA(ports->lldevs[i]) = NULL;
cxgb3i_free_big_mem(cdata);
}
@ -1821,21 +1841,27 @@ void cxgb3i_sdev_add(struct t3cdev *cdev, struct cxgb3_client *client)
struct cxgb3i_sdev_data *cdata;
struct ofld_page_info rx_page_info;
unsigned int wr_len;
int mapsize = DIV_ROUND_UP(cxgb3_max_connect,
8 * sizeof(unsigned long));
int mapsize = cxgb3_max_connect * sizeof(struct s3_conn *);
int i;
cdata = cxgb3i_alloc_big_mem(sizeof(*cdata) + mapsize, GFP_KERNEL);
if (!cdata)
if (!cdata) {
cxgb3i_log_warn("t3dev 0x%p, offload up, OOM %d.\n",
cdev, mapsize);
return;
}
if (cdev->ctl(cdev, GET_WR_LEN, &wr_len) < 0 ||
cdev->ctl(cdev, GET_PORTS, &cdata->ports) < 0 ||
cdev->ctl(cdev, GET_RX_PAGE_INFO, &rx_page_info) < 0)
cdev->ctl(cdev, GET_RX_PAGE_INFO, &rx_page_info) < 0) {
cxgb3i_log_warn("t3dev 0x%p, offload up, ioctl failed.\n",
cdev);
goto free_cdata;
}
s3_init_wr_tab(wr_len);
spin_lock_init(&cdata->lock);
INIT_LIST_HEAD(&cdata->list);
cdata->cdev = cdev;
cdata->client = client;
@ -1847,6 +1873,7 @@ void cxgb3i_sdev_add(struct t3cdev *cdev, struct cxgb3_client *client)
list_add_tail(&cdata->list, &cdata_list);
write_unlock(&cdata_rwlock);
cxgb3i_log_info("t3dev 0x%p, offload up, added.\n", cdev);
return;
free_cdata:
@ -1861,6 +1888,8 @@ void cxgb3i_sdev_remove(struct t3cdev *cdev)
{
struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(cdev);
cxgb3i_log_info("t3dev 0x%p, offload down, remove.\n", cdev);
write_lock(&cdata_rwlock);
list_del(&cdata->list);
write_unlock(&cdata_rwlock);

View file

@ -16,7 +16,7 @@
#define _CXGB3I_OFFLOAD_H
#include <linux/skbuff.h>
#include <net/tcp.h>
#include <linux/in.h>
#include "common.h"
#include "adapter.h"
@ -135,11 +135,11 @@ enum c3cn_flags {
C3CN_ABORT_RPL_PENDING, /* expecting an abort reply */
C3CN_TX_DATA_SENT, /* already sent a TX_DATA WR */
C3CN_ACTIVE_CLOSE_NEEDED, /* need to be closed */
C3CN_OFFLOAD_DOWN /* offload function off */
};
/**
* cxgb3i_sdev_data - Per adapter data.
*
* Linked off of each Ethernet device port on the adapter.
* Also available via the t3cdev structure since we have pointers to our port
* net_device's there ...
@ -148,16 +148,17 @@ enum c3cn_flags {
* @cdev: t3cdev adapter
* @client: CPL client pointer
* @ports: array of adapter ports
* @sport_map_next: next index into the port map
* @sport_map: source port map
* @sport_next: next port
* @sport_conn: source port connection
*/
struct cxgb3i_sdev_data {
struct list_head list;
struct t3cdev *cdev;
struct cxgb3_client *client;
struct adap_ports ports;
unsigned int sport_map_next;
unsigned long sport_map[0];
spinlock_t lock;
unsigned int sport_next;
struct s3_conn *sport_conn[0];
};
#define NDEV2CDATA(ndev) (*(struct cxgb3i_sdev_data **)&(ndev)->ec_ptr)
#define CXGB3_SDEV_DATA(cdev) NDEV2CDATA((cdev)->lldev)

View file

@ -1,8 +1,2 @@
# $Id: Makefile
obj-$(CONFIG_FCOE) += fcoe.o
fcoe-y := \
libfcoe.o \
fcoe_sw.o \
fc_transport_fcoe.o
obj-$(CONFIG_LIBFCOE) += libfcoe.o

View file

@ -1,443 +0,0 @@
/*
* Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Maintained at www.Open-FCoE.org
*/
#include <linux/pci.h>
#include <scsi/libfcoe.h>
#include <scsi/fc_transport_fcoe.h>
/* internal fcoe transport */
struct fcoe_transport_internal {
struct fcoe_transport *t;
struct net_device *netdev;
struct list_head list;
};
/* fcoe transports list and its lock */
static LIST_HEAD(fcoe_transports);
static DEFINE_MUTEX(fcoe_transports_lock);
/**
* fcoe_transport_default() - Returns ptr to the default transport fcoe_sw
*/
struct fcoe_transport *fcoe_transport_default(void)
{
return &fcoe_sw_transport;
}
/**
* fcoe_transport_to_pcidev() - get the pci dev from a netdev
* @netdev: the netdev that pci dev will be retrived from
*
* Returns: NULL or the corrsponding pci_dev
*/
struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev)
{
if (!netdev->dev.parent)
return NULL;
return to_pci_dev(netdev->dev.parent);
}
/**
* fcoe_transport_device_lookup() - Lookup a transport
* @netdev: the netdev the transport to be attached to
*
* This will look for existing offload driver, if not found, it falls back to
* the default sw hba (fcoe_sw) as its fcoe transport.
*
* Returns: 0 for success
*/
static struct fcoe_transport_internal *
fcoe_transport_device_lookup(struct fcoe_transport *t,
struct net_device *netdev)
{
struct fcoe_transport_internal *ti;
/* assign the transpor to this device */
mutex_lock(&t->devlock);
list_for_each_entry(ti, &t->devlist, list) {
if (ti->netdev == netdev) {
mutex_unlock(&t->devlock);
return ti;
}
}
mutex_unlock(&t->devlock);
return NULL;
}
/**
* fcoe_transport_device_add() - Assign a transport to a device
* @netdev: the netdev the transport to be attached to
*
* This will look for existing offload driver, if not found, it falls back to
* the default sw hba (fcoe_sw) as its fcoe transport.
*
* Returns: 0 for success
*/
static int fcoe_transport_device_add(struct fcoe_transport *t,
struct net_device *netdev)
{
struct fcoe_transport_internal *ti;
ti = fcoe_transport_device_lookup(t, netdev);
if (ti) {
printk(KERN_DEBUG "fcoe_transport_device_add:"
"device %s is already added to transport %s\n",
netdev->name, t->name);
return -EEXIST;
}
/* allocate an internal struct to host the netdev and the list */
ti = kzalloc(sizeof(*ti), GFP_KERNEL);
if (!ti)
return -ENOMEM;
ti->t = t;
ti->netdev = netdev;
INIT_LIST_HEAD(&ti->list);
dev_hold(ti->netdev);
mutex_lock(&t->devlock);
list_add(&ti->list, &t->devlist);
mutex_unlock(&t->devlock);
printk(KERN_DEBUG "fcoe_transport_device_add:"
"device %s added to transport %s\n",
netdev->name, t->name);
return 0;
}
/**
* fcoe_transport_device_remove() - Remove a device from its transport
* @netdev: the netdev the transport to be attached to
*
* This removes the device from the transport so the given transport will
* not manage this device any more
*
* Returns: 0 for success
*/
static int fcoe_transport_device_remove(struct fcoe_transport *t,
struct net_device *netdev)
{
struct fcoe_transport_internal *ti;
ti = fcoe_transport_device_lookup(t, netdev);
if (!ti) {
printk(KERN_DEBUG "fcoe_transport_device_remove:"
"device %s is not managed by transport %s\n",
netdev->name, t->name);
return -ENODEV;
}
mutex_lock(&t->devlock);
list_del(&ti->list);
mutex_unlock(&t->devlock);
printk(KERN_DEBUG "fcoe_transport_device_remove:"
"device %s removed from transport %s\n",
netdev->name, t->name);
dev_put(ti->netdev);
kfree(ti);
return 0;
}
/**
* fcoe_transport_device_remove_all() - Remove all from transport devlist
*
* This removes the device from the transport so the given transport will
* not manage this device any more
*
* Returns: 0 for success
*/
static void fcoe_transport_device_remove_all(struct fcoe_transport *t)
{
struct fcoe_transport_internal *ti, *tmp;
mutex_lock(&t->devlock);
list_for_each_entry_safe(ti, tmp, &t->devlist, list) {
list_del(&ti->list);
kfree(ti);
}
mutex_unlock(&t->devlock);
}
/**
* fcoe_transport_match() - Use the bus device match function to match the hw
* @t: The fcoe transport to check
* @netdev: The netdev to match against
*
* This function is used to check if the given transport wants to manage the
* input netdev. if the transports implements the match function, it will be
* called, o.w. we just compare the pci vendor and device id.
*
* Returns: true for match up
*/
static bool fcoe_transport_match(struct fcoe_transport *t,
struct net_device *netdev)
{
/* match transport by vendor and device id */
struct pci_dev *pci;
pci = fcoe_transport_pcidev(netdev);
if (pci) {
printk(KERN_DEBUG "fcoe_transport_match:"
"%s:%x:%x -- %s:%x:%x\n",
t->name, t->vendor, t->device,
netdev->name, pci->vendor, pci->device);
/* if transport supports match */
if (t->match)
return t->match(netdev);
/* else just compare the vendor and device id: pci only */
return (t->vendor == pci->vendor) && (t->device == pci->device);
}
return false;
}
/**
* fcoe_transport_lookup() - Check if the transport is already registered
* @t: the transport to be looked up
*
* This compares the parent device (pci) vendor and device id
*
* Returns: NULL if not found
*
* TODO: return default sw transport if no other transport is found
*/
static struct fcoe_transport *
fcoe_transport_lookup(struct net_device *netdev)
{
struct fcoe_transport *t;
mutex_lock(&fcoe_transports_lock);
list_for_each_entry(t, &fcoe_transports, list) {
if (fcoe_transport_match(t, netdev)) {
mutex_unlock(&fcoe_transports_lock);
return t;
}
}
mutex_unlock(&fcoe_transports_lock);
printk(KERN_DEBUG "fcoe_transport_lookup:"
"use default transport for %s\n", netdev->name);
return fcoe_transport_default();
}
/**
* fcoe_transport_register() - Adds a fcoe transport to the fcoe transports list
* @t: ptr to the fcoe transport to be added
*
* Returns: 0 for success
*/
int fcoe_transport_register(struct fcoe_transport *t)
{
struct fcoe_transport *tt;
/* TODO - add fcoe_transport specific initialization here */
mutex_lock(&fcoe_transports_lock);
list_for_each_entry(tt, &fcoe_transports, list) {
if (tt == t) {
mutex_unlock(&fcoe_transports_lock);
return -EEXIST;
}
}
list_add_tail(&t->list, &fcoe_transports);
mutex_unlock(&fcoe_transports_lock);
printk(KERN_DEBUG "fcoe_transport_register:%s\n", t->name);
return 0;
}
EXPORT_SYMBOL_GPL(fcoe_transport_register);
/**
* fcoe_transport_unregister() - Remove the tranport fro the fcoe transports list
* @t: ptr to the fcoe transport to be removed
*
* Returns: 0 for success
*/
int fcoe_transport_unregister(struct fcoe_transport *t)
{
struct fcoe_transport *tt, *tmp;
mutex_lock(&fcoe_transports_lock);
list_for_each_entry_safe(tt, tmp, &fcoe_transports, list) {
if (tt == t) {
list_del(&t->list);
mutex_unlock(&fcoe_transports_lock);
fcoe_transport_device_remove_all(t);
printk(KERN_DEBUG "fcoe_transport_unregister:%s\n",
t->name);
return 0;
}
}
mutex_unlock(&fcoe_transports_lock);
return -ENODEV;
}
EXPORT_SYMBOL_GPL(fcoe_transport_unregister);
/**
* fcoe_load_transport_driver() - Load an offload driver by alias name
* @netdev: the target net device
*
* Requests for an offload driver module as the fcoe transport, if fails, it
* falls back to use the SW HBA (fcoe_sw) as its transport
*
* TODO -
* 1. supports only PCI device
* 2. needs fix for VLAn and bonding
* 3. pure hw fcoe hba may not have netdev
*
* Returns: 0 for success
*/
int fcoe_load_transport_driver(struct net_device *netdev)
{
struct pci_dev *pci;
struct device *dev = netdev->dev.parent;
if (fcoe_transport_lookup(netdev)) {
/* load default transport */
printk(KERN_DEBUG "fcoe: already loaded transport for %s\n",
netdev->name);
return -EEXIST;
}
pci = to_pci_dev(dev);
if (dev->bus != &pci_bus_type) {
printk(KERN_DEBUG "fcoe: support noly PCI device\n");
return -ENODEV;
}
printk(KERN_DEBUG "fcoe: loading driver fcoe-pci-0x%04x-0x%04x\n",
pci->vendor, pci->device);
return request_module("fcoe-pci-0x%04x-0x%04x",
pci->vendor, pci->device);
}
EXPORT_SYMBOL_GPL(fcoe_load_transport_driver);
/**
* fcoe_transport_attach() - Load transport to fcoe
* @netdev: the netdev the transport to be attached to
*
* This will look for existing offload driver, if not found, it falls back to
* the default sw hba (fcoe_sw) as its fcoe transport.
*
* Returns: 0 for success
*/
int fcoe_transport_attach(struct net_device *netdev)
{
struct fcoe_transport *t;
/* find the corresponding transport */
t = fcoe_transport_lookup(netdev);
if (!t) {
printk(KERN_DEBUG "fcoe_transport_attach"
":no transport for %s:use %s\n",
netdev->name, t->name);
return -ENODEV;
}
/* add to the transport */
if (fcoe_transport_device_add(t, netdev)) {
printk(KERN_DEBUG "fcoe_transport_attach"
":failed to add %s to tramsport %s\n",
netdev->name, t->name);
return -EIO;
}
/* transport create function */
if (t->create)
t->create(netdev);
printk(KERN_DEBUG "fcoe_transport_attach:transport %s for %s\n",
t->name, netdev->name);
return 0;
}
EXPORT_SYMBOL_GPL(fcoe_transport_attach);
/**
* fcoe_transport_release() - Unload transport from fcoe
* @netdev: the net device on which fcoe is to be released
*
* Returns: 0 for success
*/
int fcoe_transport_release(struct net_device *netdev)
{
struct fcoe_transport *t;
/* find the corresponding transport */
t = fcoe_transport_lookup(netdev);
if (!t) {
printk(KERN_DEBUG "fcoe_transport_release:"
"no transport for %s:use %s\n",
netdev->name, t->name);
return -ENODEV;
}
/* remove the device from the transport */
if (fcoe_transport_device_remove(t, netdev)) {
printk(KERN_DEBUG "fcoe_transport_release:"
"failed to add %s to tramsport %s\n",
netdev->name, t->name);
return -EIO;
}
/* transport destroy function */
if (t->destroy)
t->destroy(netdev);
printk(KERN_DEBUG "fcoe_transport_release:"
"device %s dettached from transport %s\n",
netdev->name, t->name);
return 0;
}
EXPORT_SYMBOL_GPL(fcoe_transport_release);
/**
* fcoe_transport_init() - Initializes fcoe transport layer
*
* This prepares for the fcoe transport layer
*
* Returns: none
*/
int __init fcoe_transport_init(void)
{
INIT_LIST_HEAD(&fcoe_transports);
mutex_init(&fcoe_transports_lock);
return 0;
}
/**
* fcoe_transport_exit() - Cleans up the fcoe transport layer
*
* This cleans up the fcoe transport layer. removing any transport on the list,
* note that the transport destroy func is not called here.
*
* Returns: none
*/
int __exit fcoe_transport_exit(void)
{
struct fcoe_transport *t, *tmp;
mutex_lock(&fcoe_transports_lock);
list_for_each_entry_safe(t, tmp, &fcoe_transports, list) {
list_del(&t->list);
mutex_unlock(&fcoe_transports_lock);
fcoe_transport_device_remove_all(t);
mutex_lock(&fcoe_transports_lock);
}
mutex_unlock(&fcoe_transports_lock);
return 0;
}

1878
drivers/scsi/fcoe/fcoe.c Normal file

File diff suppressed because it is too large Load diff

75
drivers/scsi/fcoe/fcoe.h Normal file
View file

@ -0,0 +1,75 @@
/*
* Copyright(c) 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Maintained at www.Open-FCoE.org
*/
#ifndef _FCOE_H_
#define _FCOE_H_
#include <linux/skbuff.h>
#include <linux/kthread.h>
#define FCOE_MAX_QUEUE_DEPTH 256
#define FCOE_LOW_QUEUE_DEPTH 32
#define FCOE_WORD_TO_BYTE 4
#define FCOE_VERSION "0.1"
#define FCOE_NAME "fcoe"
#define FCOE_VENDOR "Open-FCoE.org"
#define FCOE_MAX_LUN 255
#define FCOE_MAX_FCP_TARGET 256
#define FCOE_MAX_OUTSTANDING_COMMANDS 1024
#define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */
#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
/*
* this percpu struct for fcoe
*/
struct fcoe_percpu_s {
struct task_struct *thread;
struct sk_buff_head fcoe_rx_list;
struct page *crc_eof_page;
int crc_eof_offset;
};
/*
* the fcoe sw transport private data
*/
struct fcoe_softc {
struct list_head list;
struct net_device *real_dev;
struct net_device *phys_dev; /* device with ethtool_ops */
struct packet_type fcoe_packet_type;
struct packet_type fip_packet_type;
struct sk_buff_head fcoe_pending_queue;
u8 fcoe_pending_queue_active;
struct fcoe_ctlr ctlr;
};
#define fcoe_from_ctlr(fc) container_of(fc, struct fcoe_softc, ctlr)
static inline struct net_device *fcoe_netdev(
const struct fc_lport *lp)
{
return ((struct fcoe_softc *)lport_priv(lp))->real_dev;
}
#endif /* _FCOE_H_ */

View file

@ -1,561 +0,0 @@
/*
* Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Maintained at www.Open-FCoE.org
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
#include <net/rtnetlink.h>
#include <scsi/fc/fc_els.h>
#include <scsi/fc/fc_encaps.h>
#include <scsi/fc/fc_fs.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/libfc.h>
#include <scsi/libfcoe.h>
#include <scsi/fc_transport_fcoe.h>
#define FCOE_SW_VERSION "0.1"
#define FCOE_SW_NAME "fcoesw"
#define FCOE_SW_VENDOR "Open-FCoE.org"
#define FCOE_MAX_LUN 255
#define FCOE_MAX_FCP_TARGET 256
#define FCOE_MAX_OUTSTANDING_COMMANDS 1024
#define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */
#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
static struct scsi_transport_template *scsi_transport_fcoe_sw;
struct fc_function_template fcoe_sw_transport_function = {
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
.show_host_supported_fc4s = 1,
.show_host_active_fc4s = 1,
.show_host_maxframe_size = 1,
.show_host_port_id = 1,
.show_host_supported_speeds = 1,
.get_host_speed = fc_get_host_speed,
.show_host_speed = 1,
.show_host_port_type = 1,
.get_host_port_state = fc_get_host_port_state,
.show_host_port_state = 1,
.show_host_symbolic_name = 1,
.dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
.show_host_fabric_name = 1,
.show_starget_node_name = 1,
.show_starget_port_name = 1,
.show_starget_port_id = 1,
.set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,
.get_fc_host_stats = fc_get_host_stats,
.issue_fc_host_lip = fcoe_reset,
.terminate_rport_io = fc_rport_terminate_io,
};
static struct scsi_host_template fcoe_sw_shost_template = {
.module = THIS_MODULE,
.name = "FCoE Driver",
.proc_name = FCOE_SW_NAME,
.queuecommand = fc_queuecommand,
.eh_abort_handler = fc_eh_abort,
.eh_device_reset_handler = fc_eh_device_reset,
.eh_host_reset_handler = fc_eh_host_reset,
.slave_alloc = fc_slave_alloc,
.change_queue_depth = fc_change_queue_depth,
.change_queue_type = fc_change_queue_type,
.this_id = -1,
.cmd_per_lun = 32,
.can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = SG_ALL,
.max_sectors = 0xffff,
};
/**
* fcoe_sw_lport_config() - sets up the fc_lport
* @lp: ptr to the fc_lport
* @shost: ptr to the parent scsi host
*
* Returns: 0 for success
*/
static int fcoe_sw_lport_config(struct fc_lport *lp)
{
int i = 0;
lp->link_up = 0;
lp->qfull = 0;
lp->max_retry_count = 3;
lp->e_d_tov = 2 * 1000; /* FC-FS default */
lp->r_a_tov = 2 * 2 * 1000;
lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
/*
* allocate per cpu stats block
*/
for_each_online_cpu(i)
lp->dev_stats[i] = kzalloc(sizeof(struct fcoe_dev_stats),
GFP_KERNEL);
/* lport fc_lport related configuration */
fc_lport_config(lp);
/* offload related configuration */
lp->crc_offload = 0;
lp->seq_offload = 0;
lp->lro_enabled = 0;
lp->lro_xid = 0;
lp->lso_max = 0;
return 0;
}
/**
* fcoe_sw_netdev_config() - Set up netdev for SW FCoE
* @lp : ptr to the fc_lport
* @netdev : ptr to the associated netdevice struct
*
* Must be called after fcoe_sw_lport_config() as it will use lport mutex
*
* Returns : 0 for success
*/
static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev)
{
u32 mfs;
u64 wwnn, wwpn;
struct fcoe_softc *fc;
u8 flogi_maddr[ETH_ALEN];
/* Setup lport private data to point to fcoe softc */
fc = lport_priv(lp);
fc->lp = lp;
fc->real_dev = netdev;
fc->phys_dev = netdev;
/* Require support for get_pauseparam ethtool op. */
if (netdev->priv_flags & IFF_802_1Q_VLAN)
fc->phys_dev = vlan_dev_real_dev(netdev);
/* Do not support for bonding device */
if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) ||
(fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) ||
(fc->real_dev->priv_flags & IFF_MASTER_8023AD)) {
return -EOPNOTSUPP;
}
/*
* Determine max frame size based on underlying device and optional
* user-configured limit. If the MFS is too low, fcoe_link_ok()
* will return 0, so do this first.
*/
mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
sizeof(struct fcoe_crc_eof));
if (fc_set_mfs(lp, mfs))
return -EINVAL;
if (!fcoe_link_ok(lp))
lp->link_up = 1;
/* offload features support */
if (fc->real_dev->features & NETIF_F_SG)
lp->sg_supp = 1;
#ifdef NETIF_F_FCOE_CRC
if (netdev->features & NETIF_F_FCOE_CRC) {
lp->crc_offload = 1;
printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n",
netdev->name);
}
#endif
#ifdef NETIF_F_FSO
if (netdev->features & NETIF_F_FSO) {
lp->seq_offload = 1;
lp->lso_max = netdev->gso_max_size;
printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n",
netdev->name, lp->lso_max);
}
#endif
if (netdev->fcoe_ddp_xid) {
lp->lro_enabled = 1;
lp->lro_xid = netdev->fcoe_ddp_xid;
printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n",
netdev->name, lp->lro_xid);
}
skb_queue_head_init(&fc->fcoe_pending_queue);
fc->fcoe_pending_queue_active = 0;
/* setup Source Mac Address */
memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr,
fc->real_dev->addr_len);
wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
fc_set_wwnn(lp, wwnn);
/* XXX - 3rd arg needs to be vlan id */
wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0);
fc_set_wwpn(lp, wwpn);
/*
* Add FCoE MAC address as second unicast MAC address
* or enter promiscuous mode if not capable of listening
* for multiple unicast MACs.
*/
rtnl_lock();
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
rtnl_unlock();
/*
* setup the receive function from ethernet driver
* on the ethertype for the given device
*/
fc->fcoe_packet_type.func = fcoe_rcv;
fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
fc->fcoe_packet_type.dev = fc->real_dev;
dev_add_pack(&fc->fcoe_packet_type);
return 0;
}
/**
* fcoe_sw_shost_config() - Sets up fc_lport->host
* @lp : ptr to the fc_lport
* @shost : ptr to the associated scsi host
* @dev : device associated to scsi host
*
* Must be called after fcoe_sw_lport_config() and fcoe_sw_netdev_config()
*
* Returns : 0 for success
*/
static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
struct device *dev)
{
int rc = 0;
/* lport scsi host config */
lp->host = shost;
lp->host->max_lun = FCOE_MAX_LUN;
lp->host->max_id = FCOE_MAX_FCP_TARGET;
lp->host->max_channel = 0;
lp->host->transportt = scsi_transport_fcoe_sw;
/* add the new host to the SCSI-ml */
rc = scsi_add_host(lp->host, dev);
if (rc) {
FC_DBG("fcoe_sw_shost_config:error on scsi_add_host\n");
return rc;
}
sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s",
FCOE_SW_NAME, FCOE_SW_VERSION,
fcoe_netdev(lp)->name);
return 0;
}
/**
* fcoe_sw_em_config() - allocates em for this lport
* @lp: the port that em is to allocated for
*
* Returns : 0 on success
*/
static inline int fcoe_sw_em_config(struct fc_lport *lp)
{
BUG_ON(lp->emp);
lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
FCOE_MIN_XID, FCOE_MAX_XID);
if (!lp->emp)
return -ENOMEM;
return 0;
}
/**
* fcoe_sw_destroy() - FCoE software HBA tear-down function
* @netdev: ptr to the associated net_device
*
* Returns: 0 if link is OK for use by FCoE.
*/
static int fcoe_sw_destroy(struct net_device *netdev)
{
int cpu;
struct fc_lport *lp = NULL;
struct fcoe_softc *fc;
u8 flogi_maddr[ETH_ALEN];
BUG_ON(!netdev);
printk(KERN_DEBUG "fcoe_sw_destroy:interface on %s\n",
netdev->name);
lp = fcoe_hostlist_lookup(netdev);
if (!lp)
return -ENODEV;
fc = lport_priv(lp);
/* Logout of the fabric */
fc_fabric_logoff(lp);
/* Remove the instance from fcoe's list */
fcoe_hostlist_remove(lp);
/* Don't listen for Ethernet packets anymore */
dev_remove_pack(&fc->fcoe_packet_type);
/* Cleanup the fc_lport */
fc_lport_destroy(lp);
fc_fcp_destroy(lp);
/* Detach from the scsi-ml */
fc_remove_host(lp->host);
scsi_remove_host(lp->host);
/* There are no more rports or I/O, free the EM */
if (lp->emp)
fc_exch_mgr_free(lp->emp);
/* Delete secondary MAC addresses */
rtnl_lock();
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
dev_unicast_delete(fc->real_dev, fc->data_src_addr, ETH_ALEN);
rtnl_unlock();
/* Free the per-CPU revieve threads */
fcoe_percpu_clean(lp);
/* Free existing skbs */
fcoe_clean_pending_queue(lp);
/* Free memory used by statistical counters */
for_each_online_cpu(cpu)
kfree(lp->dev_stats[cpu]);
/* Release the net_device and Scsi_Host */
dev_put(fc->real_dev);
scsi_host_put(lp->host);
return 0;
}
/*
* fcoe_sw_ddp_setup - calls LLD's ddp_setup through net_device
* @lp: the corresponding fc_lport
* @xid: the exchange id for this ddp transfer
* @sgl: the scatterlist describing this transfer
* @sgc: number of sg items
*
* Returns : 0 no ddp
*/
static int fcoe_sw_ddp_setup(struct fc_lport *lp, u16 xid,
struct scatterlist *sgl, unsigned int sgc)
{
struct net_device *n = fcoe_netdev(lp);
if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup)
return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc);
return 0;
}
/*
* fcoe_sw_ddp_done - calls LLD's ddp_done through net_device
* @lp: the corresponding fc_lport
* @xid: the exchange id for this ddp transfer
*
* Returns : the length of data that have been completed by ddp
*/
static int fcoe_sw_ddp_done(struct fc_lport *lp, u16 xid)
{
struct net_device *n = fcoe_netdev(lp);
if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done)
return n->netdev_ops->ndo_fcoe_ddp_done(n, xid);
return 0;
}
static struct libfc_function_template fcoe_sw_libfc_fcn_templ = {
.frame_send = fcoe_xmit,
.ddp_setup = fcoe_sw_ddp_setup,
.ddp_done = fcoe_sw_ddp_done,
};
/**
* fcoe_sw_create() - this function creates the fcoe interface
* @netdev: pointer the associated netdevice
*
* Creates fc_lport struct and scsi_host for lport, configures lport
* and starts fabric login.
*
* Returns : 0 on success
*/
static int fcoe_sw_create(struct net_device *netdev)
{
int rc;
struct fc_lport *lp = NULL;
struct fcoe_softc *fc;
struct Scsi_Host *shost;
BUG_ON(!netdev);
printk(KERN_DEBUG "fcoe_sw_create:interface on %s\n",
netdev->name);
lp = fcoe_hostlist_lookup(netdev);
if (lp)
return -EEXIST;
shost = fcoe_host_alloc(&fcoe_sw_shost_template,
sizeof(struct fcoe_softc));
if (!shost) {
FC_DBG("Could not allocate host structure\n");
return -ENOMEM;
}
lp = shost_priv(shost);
fc = lport_priv(lp);
/* configure fc_lport, e.g., em */
rc = fcoe_sw_lport_config(lp);
if (rc) {
FC_DBG("Could not configure lport\n");
goto out_host_put;
}
/* configure lport network properties */
rc = fcoe_sw_netdev_config(lp, netdev);
if (rc) {
FC_DBG("Could not configure netdev for lport\n");
goto out_host_put;
}
/* configure lport scsi host properties */
rc = fcoe_sw_shost_config(lp, shost, &netdev->dev);
if (rc) {
FC_DBG("Could not configure shost for lport\n");
goto out_host_put;
}
/* lport exch manager allocation */
rc = fcoe_sw_em_config(lp);
if (rc) {
FC_DBG("Could not configure em for lport\n");
goto out_host_put;
}
/* Initialize the library */
rc = fcoe_libfc_config(lp, &fcoe_sw_libfc_fcn_templ);
if (rc) {
FC_DBG("Could not configure libfc for lport!\n");
goto out_lp_destroy;
}
/* add to lports list */
fcoe_hostlist_add(lp);
lp->boot_time = jiffies;
fc_fabric_login(lp);
dev_hold(netdev);
return rc;
out_lp_destroy:
fc_exch_mgr_free(lp->emp); /* Free the EM */
out_host_put:
scsi_host_put(lp->host);
return rc;
}
/**
* fcoe_sw_match() - The FCoE SW transport match function
*
* Returns : false always
*/
static bool fcoe_sw_match(struct net_device *netdev)
{
/* FIXME - for sw transport, always return false */
return false;
}
/* the sw hba fcoe transport */
struct fcoe_transport fcoe_sw_transport = {
.name = "fcoesw",
.create = fcoe_sw_create,
.destroy = fcoe_sw_destroy,
.match = fcoe_sw_match,
.vendor = 0x0,
.device = 0xffff,
};
/**
* fcoe_sw_init() - Registers fcoe_sw_transport
*
* Returns : 0 on success
*/
int __init fcoe_sw_init(void)
{
/* attach to scsi transport */
scsi_transport_fcoe_sw =
fc_attach_transport(&fcoe_sw_transport_function);
if (!scsi_transport_fcoe_sw) {
printk(KERN_ERR "fcoe_sw_init:fc_attach_transport() failed\n");
return -ENODEV;
}
mutex_init(&fcoe_sw_transport.devlock);
INIT_LIST_HEAD(&fcoe_sw_transport.devlist);
/* register sw transport */
fcoe_transport_register(&fcoe_sw_transport);
return 0;
}
/**
* fcoe_sw_exit() - Unregisters fcoe_sw_transport
*
* Returns : 0 on success
*/
int __exit fcoe_sw_exit(void)
{
/* dettach the transport */
fc_release_transport(scsi_transport_fcoe_sw);
fcoe_transport_unregister(&fcoe_sw_transport);
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -75,7 +75,7 @@ MODULE_PARM_DESC(max_lun, "Maximum allowed LUN. "
module_param_named(max_targets, max_targets, uint, S_IRUGO);
MODULE_PARM_DESC(max_targets, "Maximum allowed targets. "
"[Default=" __stringify(IBMVFC_MAX_TARGETS) "]");
module_param_named(disc_threads, disc_threads, uint, S_IRUGO | S_IWUSR);
module_param_named(disc_threads, disc_threads, uint, S_IRUGO);
MODULE_PARM_DESC(disc_threads, "Number of device discovery threads to use. "
"[Default=" __stringify(IBMVFC_MAX_DISC_THREADS) "]");
module_param_named(debug, ibmvfc_debug, uint, S_IRUGO | S_IWUSR);
@ -640,6 +640,7 @@ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost)
ibmvfc_dbg(vhost, "Releasing CRQ\n");
free_irq(vdev->irq, vhost);
tasklet_kill(&vhost->tasklet);
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
@ -2699,6 +2700,25 @@ static struct ibmvfc_crq *ibmvfc_next_crq(struct ibmvfc_host *vhost)
static irqreturn_t ibmvfc_interrupt(int irq, void *dev_instance)
{
struct ibmvfc_host *vhost = (struct ibmvfc_host *)dev_instance;
unsigned long flags;
spin_lock_irqsave(vhost->host->host_lock, flags);
vio_disable_interrupts(to_vio_dev(vhost->dev));
tasklet_schedule(&vhost->tasklet);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
return IRQ_HANDLED;
}
/**
* ibmvfc_tasklet - Interrupt handler tasklet
* @data: ibmvfc host struct
*
* Returns:
* Nothing
**/
static void ibmvfc_tasklet(void *data)
{
struct ibmvfc_host *vhost = data;
struct vio_dev *vdev = to_vio_dev(vhost->dev);
struct ibmvfc_crq *crq;
struct ibmvfc_async_crq *async;
@ -2706,7 +2726,6 @@ static irqreturn_t ibmvfc_interrupt(int irq, void *dev_instance)
int done = 0;
spin_lock_irqsave(vhost->host->host_lock, flags);
vio_disable_interrupts(to_vio_dev(vhost->dev));
while (!done) {
/* Pull all the valid messages off the CRQ */
while ((crq = ibmvfc_next_crq(vhost)) != NULL) {
@ -2734,7 +2753,6 @@ static irqreturn_t ibmvfc_interrupt(int irq, void *dev_instance)
}
spin_unlock_irqrestore(vhost->host->host_lock, flags);
return IRQ_HANDLED;
}
/**
@ -3105,6 +3123,7 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
vhost->discovery_threads--;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
del_timer(&tgt->timer);
switch (status) {
case IBMVFC_MAD_SUCCESS:
@ -3160,10 +3179,90 @@ static void ibmvfc_init_passthru(struct ibmvfc_event *evt)
mad->iu.rsp.len = sizeof(mad->fc_iu.response);
}
/**
* ibmvfc_tgt_adisc_cancel_done - Completion handler when cancelling an ADISC
* @evt: ibmvfc event struct
*
* Just cleanup this event struct. Everything else is handled by
* the ADISC completion handler. If the ADISC never actually comes
* back, we still have the timer running on the ADISC event struct
* which will fire and cause the CRQ to get reset.
*
**/
static void ibmvfc_tgt_adisc_cancel_done(struct ibmvfc_event *evt)
{
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_target *tgt = evt->tgt;
tgt_dbg(tgt, "ADISC cancel complete\n");
vhost->abort_threads--;
ibmvfc_free_event(evt);
kref_put(&tgt->kref, ibmvfc_release_tgt);
wake_up(&vhost->work_wait_q);
}
/**
* ibmvfc_adisc_timeout - Handle an ADISC timeout
* @tgt: ibmvfc target struct
*
* If an ADISC times out, send a cancel. If the cancel times
* out, reset the CRQ. When the ADISC comes back as cancelled,
* log back into the target.
**/
static void ibmvfc_adisc_timeout(struct ibmvfc_target *tgt)
{
struct ibmvfc_host *vhost = tgt->vhost;
struct ibmvfc_event *evt;
struct ibmvfc_tmf *tmf;
unsigned long flags;
int rc;
tgt_dbg(tgt, "ADISC timeout\n");
spin_lock_irqsave(vhost->host->host_lock, flags);
if (vhost->abort_threads >= disc_threads ||
tgt->action != IBMVFC_TGT_ACTION_INIT_WAIT ||
vhost->state != IBMVFC_INITIALIZING ||
vhost->action != IBMVFC_HOST_ACTION_QUERY_TGTS) {
spin_unlock_irqrestore(vhost->host->host_lock, flags);
return;
}
vhost->abort_threads++;
kref_get(&tgt->kref);
evt = ibmvfc_get_event(vhost);
ibmvfc_init_event(evt, ibmvfc_tgt_adisc_cancel_done, IBMVFC_MAD_FORMAT);
evt->tgt = tgt;
tmf = &evt->iu.tmf;
memset(tmf, 0, sizeof(*tmf));
tmf->common.version = 1;
tmf->common.opcode = IBMVFC_TMF_MAD;
tmf->common.length = sizeof(*tmf);
tmf->scsi_id = tgt->scsi_id;
tmf->cancel_key = tgt->cancel_key;
rc = ibmvfc_send_event(evt, vhost, default_timeout);
if (rc) {
tgt_err(tgt, "Failed to send cancel event for ADISC. rc=%d\n", rc);
vhost->abort_threads--;
kref_put(&tgt->kref, ibmvfc_release_tgt);
__ibmvfc_reset_host(vhost);
} else
tgt_dbg(tgt, "Attempting to cancel ADISC\n");
spin_unlock_irqrestore(vhost->host->host_lock, flags);
}
/**
* ibmvfc_tgt_adisc - Initiate an ADISC for specified target
* @tgt: ibmvfc target struct
*
* When sending an ADISC we end up with two timers running. The
* first timer is the timer in the ibmvfc target struct. If this
* fires, we send a cancel to the target. The second timer is the
* timer on the ibmvfc event for the ADISC, which is longer. If that
* fires, it means the ADISC timed out and our attempt to cancel it
* also failed, so we need to reset the CRQ.
**/
static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
{
@ -3184,6 +3283,7 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
mad = &evt->iu.passthru;
mad->iu.flags = IBMVFC_FC_ELS;
mad->iu.scsi_id = tgt->scsi_id;
mad->iu.cancel_key = tgt->cancel_key;
mad->fc_iu.payload[0] = IBMVFC_ADISC;
memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name,
@ -3192,9 +3292,19 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
sizeof(vhost->login_buf->resp.node_name));
mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff;
if (timer_pending(&tgt->timer))
mod_timer(&tgt->timer, jiffies + (IBMVFC_ADISC_TIMEOUT * HZ));
else {
tgt->timer.data = (unsigned long) tgt;
tgt->timer.expires = jiffies + (IBMVFC_ADISC_TIMEOUT * HZ);
tgt->timer.function = (void (*)(unsigned long))ibmvfc_adisc_timeout;
add_timer(&tgt->timer);
}
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
if (ibmvfc_send_event(evt, vhost, IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT)) {
vhost->discovery_threads--;
del_timer(&tgt->timer);
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
kref_put(&tgt->kref, ibmvfc_release_tgt);
} else
@ -3322,6 +3432,8 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id)
tgt->new_scsi_id = scsi_id;
tgt->vhost = vhost;
tgt->need_login = 1;
tgt->cancel_key = vhost->task_set++;
init_timer(&tgt->timer);
kref_init(&tgt->kref);
ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
spin_lock_irqsave(vhost->host->host_lock, flags);
@ -3716,6 +3828,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
spin_unlock_irqrestore(vhost->host->host_lock, flags);
if (rport)
fc_remote_port_delete(rport);
del_timer_sync(&tgt->timer);
kref_put(&tgt->kref, ibmvfc_release_tgt);
return;
}
@ -3859,6 +3972,8 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
retrc = 0;
tasklet_init(&vhost->tasklet, (void *)ibmvfc_tasklet, (unsigned long)vhost);
if ((rc = request_irq(vdev->irq, ibmvfc_interrupt, 0, IBMVFC_NAME, vhost))) {
dev_err(dev, "Couldn't register irq 0x%x. rc=%d\n", vdev->irq, rc);
goto req_irq_failed;
@ -3874,6 +3989,7 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
return retrc;
req_irq_failed:
tasklet_kill(&vhost->tasklet);
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
@ -4040,6 +4156,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
vhost->dev = dev;
vhost->partition_number = -1;
vhost->log_level = log_level;
vhost->task_set = 1;
strcpy(vhost->partition_name, "UNKNOWN");
init_waitqueue_head(&vhost->work_wait_q);
init_waitqueue_head(&vhost->init_wait_q);
@ -4174,6 +4291,7 @@ static struct fc_function_template ibmvfc_transport_functions = {
.show_host_supported_classes = 1,
.show_host_port_type = 1,
.show_host_port_id = 1,
.show_host_maxframe_size = 1,
.get_host_port_state = ibmvfc_get_host_port_state,
.show_host_port_state = 1,

View file

@ -29,10 +29,14 @@
#include "viosrp.h"
#define IBMVFC_NAME "ibmvfc"
#define IBMVFC_DRIVER_VERSION "1.0.4"
#define IBMVFC_DRIVER_DATE "(November 14, 2008)"
#define IBMVFC_DRIVER_VERSION "1.0.5"
#define IBMVFC_DRIVER_DATE "(March 19, 2009)"
#define IBMVFC_DEFAULT_TIMEOUT 60
#define IBMVFC_ADISC_CANCEL_TIMEOUT 45
#define IBMVFC_ADISC_TIMEOUT 15
#define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \
(IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT)
#define IBMVFC_INIT_TIMEOUT 120
#define IBMVFC_MAX_REQUESTS_DEFAULT 100
@ -53,9 +57,9 @@
* Ensure we have resources for ERP and initialization:
* 1 for ERP
* 1 for initialization
* 1 for each discovery thread
* 2 for each discovery thread
*/
#define IBMVFC_NUM_INTERNAL_REQ (1 + 1 + disc_threads)
#define IBMVFC_NUM_INTERNAL_REQ (1 + 1 + (disc_threads * 2))
#define IBMVFC_MAD_SUCCESS 0x00
#define IBMVFC_MAD_NOT_SUPPORTED 0xF1
@ -585,10 +589,12 @@ struct ibmvfc_target {
enum ibmvfc_target_action action;
int need_login;
int init_retries;
u32 cancel_key;
struct ibmvfc_service_parms service_parms;
struct ibmvfc_service_parms service_parms_change;
struct fc_rport_identifiers ids;
void (*job_step) (struct ibmvfc_target *);
struct timer_list timer;
struct kref kref;
};
@ -672,6 +678,7 @@ struct ibmvfc_host {
int task_set;
int init_retries;
int discovery_threads;
int abort_threads;
int client_migrated;
int reinit;
int delay_init;
@ -684,6 +691,7 @@ struct ibmvfc_host {
char partition_name[97];
void (*job_step) (struct ibmvfc_host *);
struct task_struct *work_thread;
struct tasklet_struct tasklet;
wait_queue_head_t init_wait_q;
wait_queue_head_t work_wait_q;
};

View file

@ -41,7 +41,7 @@
MODULE_AUTHOR("Open-FCoE.org");
MODULE_DESCRIPTION("libfc");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL v2");
static int fc_fcp_debug;
@ -407,10 +407,12 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
if (~crc != le32_to_cpu(fr_crc(fp))) {
crc_err:
stats = lp->dev_stats[smp_processor_id()];
stats = fc_lport_get_stats(lp);
stats->ErrorFrames++;
/* FIXME - per cpu count, not total count! */
if (stats->InvalidCRCCount++ < 5)
FC_DBG("CRC error on data frame\n");
printk(KERN_WARNING "CRC error on data frame for port (%6x)\n",
fc_host_port_id(lp->host));
/*
* Assume the frame is total garbage.
* We may have copied it over the good part
@ -1752,7 +1754,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
/*
* setup the data direction
*/
stats = lp->dev_stats[smp_processor_id()];
stats = fc_lport_get_stats(lp);
if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) {
fsp->req_flags = FC_SRB_READ;
stats->InputRequests++;

View file

@ -267,10 +267,10 @@ EXPORT_SYMBOL(fc_get_host_speed);
struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
{
int i;
struct fc_host_statistics *fcoe_stats;
struct fc_lport *lp = shost_priv(shost);
struct timespec v0, v1;
unsigned int cpu;
fcoe_stats = &lp->host_stats;
memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
@ -279,10 +279,11 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
jiffies_to_timespec(lp->boot_time, &v1);
fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec);
for_each_online_cpu(i) {
struct fcoe_dev_stats *stats = lp->dev_stats[i];
if (stats == NULL)
continue;
for_each_possible_cpu(cpu) {
struct fcoe_dev_stats *stats;
stats = per_cpu_ptr(lp->dev_stats, cpu);
fcoe_stats->tx_frames += stats->TxFrames;
fcoe_stats->tx_words += stats->TxWords;
fcoe_stats->rx_frames += stats->RxFrames;

View file

@ -1999,8 +1999,10 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
GFP_KERNEL, NULL);
if (q->queue == ERR_PTR(-ENOMEM))
if (IS_ERR(q->queue)) {
q->queue = NULL;
goto enomem;
}
for (i = 0; i < max; i++) {
q->pool[i] = kzalloc(item_size, GFP_KERNEL);

View file

@ -338,20 +338,6 @@ struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
}
EXPORT_SYMBOL(osd_start_request);
/*
* If osd_finalize_request() was called but the request was not executed through
* the block layer, then we must release BIOs.
*/
static void _abort_unexecuted_bios(struct request *rq)
{
struct bio *bio;
while ((bio = rq->bio) != NULL) {
rq->bio = bio->bi_next;
bio_endio(bio, 0);
}
}
static void _osd_free_seg(struct osd_request *or __unused,
struct _osd_req_data_segment *seg)
{
@ -363,9 +349,30 @@ static void _osd_free_seg(struct osd_request *or __unused,
seg->alloc_size = 0;
}
static void _put_request(struct request *rq , bool is_async)
{
if (is_async) {
WARN_ON(rq->bio);
__blk_put_request(rq->q, rq);
} else {
/*
* If osd_finalize_request() was called but the request was not
* executed through the block layer, then we must release BIOs.
* TODO: Keep error code in or->async_error. Need to audit all
* code paths.
*/
if (unlikely(rq->bio))
blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
else
blk_put_request(rq);
}
}
void osd_end_request(struct osd_request *or)
{
struct request *rq = or->request;
/* IMPORTANT: make sure this agrees with osd_execute_request_async */
bool is_async = (or->request->end_io_data == or);
_osd_free_seg(or, &or->set_attr);
_osd_free_seg(or, &or->enc_get_attr);
@ -373,12 +380,11 @@ void osd_end_request(struct osd_request *or)
if (rq) {
if (rq->next_rq) {
_abort_unexecuted_bios(rq->next_rq);
blk_put_request(rq->next_rq);
_put_request(rq->next_rq, is_async);
rq->next_rq = NULL;
}
_abort_unexecuted_bios(rq);
blk_put_request(rq);
_put_request(rq, is_async);
}
_osd_request_free(or);
}

View file

@ -345,10 +345,6 @@ static int osd_probe(struct device *dev)
}
dev_set_drvdata(oud->class_member, oud);
error = sysfs_create_link(&scsi_device->sdev_gendev.kobj,
&oud->class_member->kobj, osd_symlink);
if (error)
OSD_ERR("warning: unable to make symlink\n");
OSD_INFO("osd_probe %s\n", disk->disk_name);
return 0;
@ -377,8 +373,6 @@ static int osd_remove(struct device *dev)
scsi_device);
}
sysfs_remove_link(&oud->od.scsi_device->sdev_gendev.kobj, osd_symlink);
if (oud->class_member)
device_destroy(osd_sysfs_class,
MKDEV(SCSI_OSD_MAJOR, oud->minor));

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -348,6 +348,7 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <asm/io.h>
#include <asm/irq.h>
@ -384,11 +385,7 @@
#define MEMORY_MAPPED_IO 1
#endif
#define UNIQUE_FW_NAME
#include "qla1280.h"
#include "ql12160_fw.h" /* ISP RISC codes */
#include "ql1280_fw.h"
#include "ql1040_fw.h"
#ifndef BITS_PER_LONG
#error "BITS_PER_LONG not defined!"
@ -541,10 +538,7 @@ __setup("qla1280=", qla1280_setup);
struct qla_boards {
unsigned char name[9]; /* Board ID String */
int numPorts; /* Number of SCSI ports */
unsigned short *fwcode; /* pointer to FW array */
unsigned short *fwlen; /* number of words in array */
unsigned short *fwstart; /* start address for F/W */
unsigned char *fwver; /* Ptr to F/W version array */
char *fwname; /* firmware name */
};
/* NOTE: the last argument in each entry is used to index ql1280_board_tbl */
@ -567,19 +561,13 @@ MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl);
static struct qla_boards ql1280_board_tbl[] = {
/* Name , Number of ports, FW details */
{"QLA12160", 2, &fw12160i_code01[0], &fw12160i_length01,
&fw12160i_addr01, &fw12160i_version_str[0]},
{"QLA1040", 1, &risc_code01[0], &risc_code_length01,
&risc_code_addr01, &firmware_version[0]},
{"QLA1080", 1, &fw1280ei_code01[0], &fw1280ei_length01,
&fw1280ei_addr01, &fw1280ei_version_str[0]},
{"QLA1240", 2, &fw1280ei_code01[0], &fw1280ei_length01,
&fw1280ei_addr01, &fw1280ei_version_str[0]},
{"QLA1280", 2, &fw1280ei_code01[0], &fw1280ei_length01,
&fw1280ei_addr01, &fw1280ei_version_str[0]},
{"QLA10160", 1, &fw12160i_code01[0], &fw12160i_length01,
&fw12160i_addr01, &fw12160i_version_str[0]},
{" ", 0}
{"QLA12160", 2, "qlogic/12160.bin"},
{"QLA1040", 1, "qlogic/1040.bin"},
{"QLA1080", 1, "qlogic/1280.bin"},
{"QLA1240", 2, "qlogic/1280.bin"},
{"QLA1280", 2, "qlogic/1280.bin"},
{"QLA10160", 1, "qlogic/12160.bin"},
{" ", 0, " "},
};
static int qla1280_verbose = 1;
@ -704,7 +692,7 @@ qla1280_info(struct Scsi_Host *host)
sprintf (bp,
"QLogic %s PCI to SCSI Host Adapter\n"
" Firmware version: %2d.%02d.%02d, Driver version %s",
&bdp->name[0], bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
&bdp->name[0], ha->fwver1, ha->fwver2, ha->fwver3,
QLA1280_VERSION);
return bp;
}
@ -1648,36 +1636,60 @@ qla1280_chip_diag(struct scsi_qla_host *ha)
static int
qla1280_load_firmware_pio(struct scsi_qla_host *ha)
{
uint16_t risc_address, *risc_code_address, risc_code_size;
const struct firmware *fw;
const __le16 *fw_data;
uint16_t risc_address, risc_code_size;
uint16_t mb[MAILBOX_REGISTER_COUNT], i;
int err;
err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
&ha->pdev->dev);
if (err) {
printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
ql1280_board_tbl[ha->devnum].fwname, err);
return err;
}
if ((fw->size % 2) || (fw->size < 6)) {
printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
fw->size, ql1280_board_tbl[ha->devnum].fwname);
err = -EINVAL;
goto out;
}
ha->fwver1 = fw->data[0];
ha->fwver2 = fw->data[1];
ha->fwver3 = fw->data[2];
fw_data = (const __le16 *)&fw->data[0];
ha->fwstart = __le16_to_cpu(fw_data[2]);
/* Load RISC code. */
risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
risc_address = ha->fwstart;
fw_data = (const __le16 *)&fw->data[4];
risc_code_size = (fw->size - 6) / 2;
for (i = 0; i < risc_code_size; i++) {
mb[0] = MBC_WRITE_RAM_WORD;
mb[1] = risc_address + i;
mb[2] = risc_code_address[i];
mb[2] = __le16_to_cpu(fw_data[i]);
err = qla1280_mailbox_command(ha, BIT_0 | BIT_1 | BIT_2, mb);
if (err) {
printk(KERN_ERR "scsi(%li): Failed to load firmware\n",
ha->host_no);
return err;
goto out;
}
}
return 0;
out:
release_firmware(fw);
return err;
}
#define DUMP_IT_BACK 0 /* for debug of RISC loading */
static int
qla1280_load_firmware_dma(struct scsi_qla_host *ha)
{
uint16_t risc_address, *risc_code_address, risc_code_size;
const struct firmware *fw;
const __le16 *fw_data;
uint16_t risc_address, risc_code_size;
uint16_t mb[MAILBOX_REGISTER_COUNT], cnt;
int err = 0, num, i;
#if DUMP_IT_BACK
@ -1689,10 +1701,29 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
return -ENOMEM;
#endif
err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
&ha->pdev->dev);
if (err) {
printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
ql1280_board_tbl[ha->devnum].fwname, err);
return err;
}
if ((fw->size % 2) || (fw->size < 6)) {
printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
fw->size, ql1280_board_tbl[ha->devnum].fwname);
err = -EINVAL;
goto out;
}
ha->fwver1 = fw->data[0];
ha->fwver2 = fw->data[1];
ha->fwver3 = fw->data[2];
fw_data = (const __le16 *)&fw->data[0];
ha->fwstart = __le16_to_cpu(fw_data[2]);
/* Load RISC code. */
risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
risc_address = ha->fwstart;
fw_data = (const __le16 *)&fw->data[4];
risc_code_size = (fw->size - 6) / 2;
dprintk(1, "%s: DMA RISC code (%i) words\n",
__func__, risc_code_size);
@ -1708,10 +1739,9 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
dprintk(2, "qla1280_setup_chip: loading risc @ =(0x%p),"
"%d,%d(0x%x)\n",
risc_code_address, cnt, num, risc_address);
fw_data, cnt, num, risc_address);
for(i = 0; i < cnt; i++)
((__le16 *)ha->request_ring)[i] =
cpu_to_le16(risc_code_address[i]);
((__le16 *)ha->request_ring)[i] = fw_data[i];
mb[0] = MBC_LOAD_RAM;
mb[1] = risc_address;
@ -1763,7 +1793,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
#endif
risc_address += cnt;
risc_code_size = risc_code_size - cnt;
risc_code_address = risc_code_address + cnt;
fw_data = fw_data + cnt;
num++;
}
@ -1771,6 +1801,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
#if DUMP_IT_BACK
pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
#endif
release_firmware(fw);
return err;
}
@ -1786,7 +1817,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
/* Verify checksum of loaded RISC code. */
mb[0] = MBC_VERIFY_CHECKSUM;
/* mb[1] = ql12_risc_code_addr01; */
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
mb[1] = ha->fwstart;
err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
if (err) {
printk(KERN_ERR "scsi(%li): RISC checksum failed.\n", ha->host_no);
@ -1796,7 +1827,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
/* Start firmware execution. */
dprintk(1, "%s: start firmware running.\n", __func__);
mb[0] = MBC_EXECUTE_FIRMWARE;
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
mb[1] = ha->fwstart;
err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
if (err) {
printk(KERN_ERR "scsi(%li): Failed to start firmware\n",
@ -4450,6 +4481,9 @@ module_exit(qla1280_exit);
MODULE_AUTHOR("Qlogic & Jes Sorensen");
MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("qlogic/1040.bin");
MODULE_FIRMWARE("qlogic/1280.bin");
MODULE_FIRMWARE("qlogic/12160.bin");
MODULE_VERSION(QLA1280_VERSION);
/*

View file

@ -1069,6 +1069,12 @@ struct scsi_qla_host {
struct nvram nvram;
int nvram_valid;
/* Firmware Info */
unsigned short fwstart; /* start address for F/W */
unsigned char fwver1; /* F/W version first char */
unsigned char fwver2; /* F/W version second char */
unsigned char fwver3; /* F/W version third char */
};
#endif /* _QLA1280_H */

View file

@ -96,7 +96,9 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return 0;
/* Read NVRAM data from cache. */
if (IS_NOCACHE_VPD_TYPE(ha))
ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_nvram << 2,
ha->nvram_size);
return memory_read_from_buffer(buf, count, &off, ha->nvram,
ha->nvram_size);
}
@ -111,7 +113,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
struct qla_hw_data *ha = vha->hw;
uint16_t cnt;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size ||
!ha->isp_ops->write_nvram)
return 0;
/* Checksum NVRAM. */
@ -137,12 +140,21 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
*iter = chksum;
}
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"HBA not online, failing NVRAM update.\n");
return -EAGAIN;
}
/* Write NVRAM. */
ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count);
ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base,
count);
/* NVRAM settings take effect immediately. */
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_chip_reset(vha);
return (count);
}
@ -330,6 +342,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
if (ha->optrom_state != QLA_SWRITING)
break;
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"HBA not online, failing flash update.\n");
return -EAGAIN;
}
DEBUG2(qla_printk(KERN_INFO, ha,
"Writing flash region -- 0x%x/0x%x.\n",
ha->optrom_region_start, ha->optrom_region_size));
@ -364,7 +382,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return 0;
/* Read NVRAM data from cache. */
if (IS_NOCACHE_VPD_TYPE(ha))
ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
ha->vpd_size);
return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
}
@ -376,14 +396,35 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj,
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
uint8_t *tmp_data;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size ||
!ha->isp_ops->write_nvram)
return 0;
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"HBA not online, failing VPD update.\n");
return -EAGAIN;
}
/* Write NVRAM. */
ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count);
ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count);
/* Update flash version information for 4Gb & above. */
if (!IS_FWI2_CAPABLE(ha))
goto done;
tmp_data = vmalloc(256);
if (!tmp_data) {
qla_printk(KERN_WARNING, ha,
"Unable to allocate memory for VPD information update.\n");
goto done;
}
ha->isp_ops->get_flash_version(vha, tmp_data);
vfree(tmp_data);
done:
return count;
}
@ -458,6 +499,199 @@ static struct bin_attribute sysfs_sfp_attr = {
.read = qla2x00_sysfs_read_sfp,
};
static ssize_t
qla2x00_sysfs_write_reset(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
int type;
if (off != 0)
return 0;
type = simple_strtol(buf, NULL, 10);
switch (type) {
case 0x2025c:
qla_printk(KERN_INFO, ha,
"Issuing ISP reset on (%ld).\n", vha->host_no);
scsi_block_requests(vha->host);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_chip_reset(vha);
scsi_unblock_requests(vha->host);
break;
case 0x2025d:
if (!IS_QLA81XX(ha))
break;
qla_printk(KERN_INFO, ha,
"Issuing MPI reset on (%ld).\n", vha->host_no);
/* Make sure FC side is not in reset */
qla2x00_wait_for_hba_online(vha);
/* Issue MPI reset */
scsi_block_requests(vha->host);
if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS)
qla_printk(KERN_WARNING, ha,
"MPI reset failed on (%ld).\n", vha->host_no);
scsi_unblock_requests(vha->host);
break;
}
return count;
}
static struct bin_attribute sysfs_reset_attr = {
.attr = {
.name = "reset",
.mode = S_IWUSR,
},
.size = 0,
.write = qla2x00_sysfs_write_reset,
};
static ssize_t
qla2x00_sysfs_write_edc(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
uint16_t dev, adr, opt, len;
int rval;
ha->edc_data_len = 0;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8)
return 0;
if (!ha->edc_data) {
ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
&ha->edc_data_dma);
if (!ha->edc_data) {
DEBUG2(qla_printk(KERN_INFO, ha,
"Unable to allocate memory for EDC write.\n"));
return 0;
}
}
dev = le16_to_cpup((void *)&buf[0]);
adr = le16_to_cpup((void *)&buf[2]);
opt = le16_to_cpup((void *)&buf[4]);
len = le16_to_cpup((void *)&buf[6]);
if (!(opt & BIT_0))
if (len == 0 || len > DMA_POOL_SIZE || len > count - 8)
return -EINVAL;
memcpy(ha->edc_data, &buf[8], len);
rval = qla2x00_write_edc(vha, dev, adr, ha->edc_data_dma,
ha->edc_data, len, opt);
if (rval != QLA_SUCCESS) {
DEBUG2(qla_printk(KERN_INFO, ha,
"Unable to write EDC (%x) %02x:%02x:%04x:%02x:%02x.\n",
rval, dev, adr, opt, len, *buf));
return 0;
}
return count;
}
static struct bin_attribute sysfs_edc_attr = {
.attr = {
.name = "edc",
.mode = S_IWUSR,
},
.size = 0,
.write = qla2x00_sysfs_write_edc,
};
static ssize_t
qla2x00_sysfs_write_edc_status(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
uint16_t dev, adr, opt, len;
int rval;
ha->edc_data_len = 0;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8)
return 0;
if (!ha->edc_data) {
ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
&ha->edc_data_dma);
if (!ha->edc_data) {
DEBUG2(qla_printk(KERN_INFO, ha,
"Unable to allocate memory for EDC status.\n"));
return 0;
}
}
dev = le16_to_cpup((void *)&buf[0]);
adr = le16_to_cpup((void *)&buf[2]);
opt = le16_to_cpup((void *)&buf[4]);
len = le16_to_cpup((void *)&buf[6]);
if (!(opt & BIT_0))
if (len == 0 || len > DMA_POOL_SIZE)
return -EINVAL;
memset(ha->edc_data, 0, len);
rval = qla2x00_read_edc(vha, dev, adr, ha->edc_data_dma,
ha->edc_data, len, opt);
if (rval != QLA_SUCCESS) {
DEBUG2(qla_printk(KERN_INFO, ha,
"Unable to write EDC status (%x) %02x:%02x:%04x:%02x.\n",
rval, dev, adr, opt, len));
return 0;
}
ha->edc_data_len = len;
return count;
}
static ssize_t
qla2x00_sysfs_read_edc_status(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count == 0)
return 0;
if (!ha->edc_data || ha->edc_data_len == 0 || ha->edc_data_len > count)
return -EINVAL;
memcpy(buf, ha->edc_data, ha->edc_data_len);
return ha->edc_data_len;
}
static struct bin_attribute sysfs_edc_status_attr = {
.attr = {
.name = "edc_status",
.mode = S_IRUSR | S_IWUSR,
},
.size = 0,
.write = qla2x00_sysfs_write_edc_status,
.read = qla2x00_sysfs_read_edc_status,
};
static struct sysfs_entry {
char *name;
struct bin_attribute *attr;
@ -469,6 +703,9 @@ static struct sysfs_entry {
{ "optrom_ctl", &sysfs_optrom_ctl_attr, },
{ "vpd", &sysfs_vpd_attr, 1 },
{ "sfp", &sysfs_sfp_attr, 1 },
{ "reset", &sysfs_reset_attr, },
{ "edc", &sysfs_edc_attr, 2 },
{ "edc_status", &sysfs_edc_status_attr, 2 },
{ NULL },
};
@ -482,6 +719,8 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
for (iter = bin_file_entries; iter->name; iter++) {
if (iter->is4GBp_only && !IS_FWI2_CAPABLE(vha->hw))
continue;
if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw))
continue;
ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
iter->attr);
@ -502,6 +741,8 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha)
for (iter = bin_file_entries; iter->name; iter++) {
if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha))
continue;
if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha))
continue;
sysfs_remove_bin_file(&host->shost_gendev.kobj,
iter->attr);
@ -818,9 +1059,33 @@ qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr,
if (!IS_QLA81XX(ha))
return snprintf(buf, PAGE_SIZE, "\n");
return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x (%x)\n",
return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n",
ha->mpi_version[0], ha->mpi_version[1], ha->mpi_version[2],
ha->mpi_version[3], ha->mpi_capabilities);
ha->mpi_capabilities);
}
static ssize_t
qla2x00_phy_version_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
if (!IS_QLA81XX(ha))
return snprintf(buf, PAGE_SIZE, "\n");
return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n",
ha->phy_version[0], ha->phy_version[1], ha->phy_version[2]);
}
static ssize_t
qla2x00_flash_block_size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
return snprintf(buf, PAGE_SIZE, "0x%x\n", ha->fdt_block_size);
}
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
@ -848,6 +1113,9 @@ static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
NULL);
static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL);
static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL);
static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show,
NULL);
struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_driver_version,
@ -868,6 +1136,8 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_optrom_fw_version,
&dev_attr_total_isp_aborts,
&dev_attr_mpi_version,
&dev_attr_phy_version,
&dev_attr_flash_block_size,
NULL,
};
@ -1012,7 +1282,10 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
if (!fcport)
return;
qla2x00_abort_fcport_cmds(fcport);
if (unlikely(pci_channel_offline(fcport->vha->hw->pdev)))
qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
else
qla2x00_abort_fcport_cmds(fcport);
/*
* Transport has effectively 'deleted' the rport, clear
@ -1032,16 +1305,18 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
if (!fcport)
return;
if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
return;
}
/*
* At this point all fcport's software-states are cleared. Perform any
* final cleanup of firmware resources (PCBs and XCBs).
*/
if (fcport->loop_id != FC_NO_LOOP_ID) {
if (fcport->loop_id != FC_NO_LOOP_ID)
fcport->vha->hw->isp_ops->fabric_logout(fcport->vha,
fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa);
fcport->loop_id = FC_NO_LOOP_ID;
}
qla2x00_abort_fcport_cmds(fcport);
}

View file

@ -176,8 +176,7 @@
/* ISP request and response entry counts (37-65535) */
#define REQUEST_ENTRY_CNT_2100 128 /* Number of request entries. */
#define REQUEST_ENTRY_CNT_2200 2048 /* Number of request entries. */
#define REQUEST_ENTRY_CNT_2XXX_EXT_MEM 4096 /* Number of request entries. */
#define REQUEST_ENTRY_CNT_24XX 4096 /* Number of request entries. */
#define REQUEST_ENTRY_CNT_24XX 2048 /* Number of request entries. */
#define RESPONSE_ENTRY_CNT_2100 64 /* Number of response entries.*/
#define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/
@ -201,20 +200,7 @@ typedef struct srb {
/*
* SRB flag definitions
*/
#define SRB_TIMEOUT BIT_0 /* Command timed out */
#define SRB_DMA_VALID BIT_1 /* Command sent to ISP */
#define SRB_WATCHDOG BIT_2 /* Command on watchdog list */
#define SRB_ABORT_PENDING BIT_3 /* Command abort sent to device */
#define SRB_ABORTED BIT_4 /* Command aborted command already */
#define SRB_RETRY BIT_5 /* Command needs retrying */
#define SRB_GOT_SENSE BIT_6 /* Command has sense data */
#define SRB_FAILOVER BIT_7 /* Command in failover state */
#define SRB_BUSY BIT_8 /* Command is in busy retry state */
#define SRB_FO_CANCEL BIT_9 /* Command don't need to do failover */
#define SRB_IOCTL BIT_10 /* IOCTL command. */
#define SRB_TAPE BIT_11 /* FCP2 (Tape) command. */
#define SRB_DMA_VALID BIT_0 /* Command sent to ISP */
/*
* ISP I/O Register Set structure definitions.
@ -372,10 +358,10 @@ struct device_reg_2xxx {
};
struct device_reg_25xxmq {
volatile uint32_t req_q_in;
volatile uint32_t req_q_out;
volatile uint32_t rsp_q_in;
volatile uint32_t rsp_q_out;
uint32_t req_q_in;
uint32_t req_q_out;
uint32_t rsp_q_in;
uint32_t rsp_q_out;
};
typedef union {
@ -620,6 +606,7 @@ typedef struct {
#define MBC_GET_TIMEOUT_PARAMS 0x22 /* Get FW timeouts. */
#define MBC_TRACE_CONTROL 0x27 /* Trace control command. */
#define MBC_GEN_SYSTEM_ERROR 0x2a /* Generate System Error. */
#define MBC_WRITE_SFP 0x30 /* Write SFP Data. */
#define MBC_READ_SFP 0x31 /* Read SFP Data. */
#define MBC_SET_TIMEOUT_PARAMS 0x32 /* Set FW timeouts. */
#define MBC_MID_INITIALIZE_FIRMWARE 0x48 /* MID Initialize firmware. */
@ -1570,39 +1557,13 @@ typedef struct fc_port {
#define FCS_DEVICE_DEAD 2
#define FCS_DEVICE_LOST 3
#define FCS_ONLINE 4
#define FCS_NOT_SUPPORTED 5
#define FCS_FAILOVER 6
#define FCS_FAILOVER_FAILED 7
/*
* FC port flags.
*/
#define FCF_FABRIC_DEVICE BIT_0
#define FCF_LOGIN_NEEDED BIT_1
#define FCF_FO_MASKED BIT_2
#define FCF_FAILOVER_NEEDED BIT_3
#define FCF_RESET_NEEDED BIT_4
#define FCF_PERSISTENT_BOUND BIT_5
#define FCF_TAPE_PRESENT BIT_6
#define FCF_FARP_DONE BIT_7
#define FCF_FARP_FAILED BIT_8
#define FCF_FARP_REPLY_NEEDED BIT_9
#define FCF_AUTH_REQ BIT_10
#define FCF_SEND_AUTH_REQ BIT_11
#define FCF_RECEIVE_AUTH_REQ BIT_12
#define FCF_AUTH_SUCCESS BIT_13
#define FCF_RLC_SUPPORT BIT_14
#define FCF_CONFIG BIT_15 /* Needed? */
#define FCF_RESCAN_NEEDED BIT_16
#define FCF_XP_DEVICE BIT_17
#define FCF_MSA_DEVICE BIT_18
#define FCF_EVA_DEVICE BIT_19
#define FCF_MSA_PORT_ACTIVE BIT_20
#define FCF_FAILBACK_DISABLE BIT_21
#define FCF_FAILOVER_DISABLE BIT_22
#define FCF_DSXXX_DEVICE BIT_23
#define FCF_AA_EVA_DEVICE BIT_24
#define FCF_AA_MSA_DEVICE BIT_25
#define FCF_TAPE_PRESENT BIT_2
/* No loop ID flag. */
#define FC_NO_LOOP_ID 0x1000
@ -2102,9 +2063,6 @@ struct isp_operations {
int (*get_flash_version) (struct scsi_qla_host *, void *);
int (*start_scsi) (srb_t *);
void (*wrt_req_reg) (struct qla_hw_data *, uint16_t, uint16_t);
void (*wrt_rsp_reg) (struct qla_hw_data *, uint16_t, uint16_t);
uint16_t (*rd_req_reg) (struct qla_hw_data *, uint16_t);
};
/* MSI-X Support *************************************************************/
@ -2200,6 +2158,8 @@ struct rsp_que {
dma_addr_t dma;
response_t *ring;
response_t *ring_ptr;
uint32_t __iomem *rsp_q_in; /* FWI2-capable only. */
uint32_t __iomem *rsp_q_out;
uint16_t ring_index;
uint16_t out_ptr;
uint16_t length;
@ -2217,6 +2177,8 @@ struct req_que {
dma_addr_t dma;
request_t *ring;
request_t *ring_ptr;
uint32_t __iomem *req_q_in; /* FWI2-capable only. */
uint32_t __iomem *req_q_out;
uint16_t ring_index;
uint16_t in_ptr;
uint16_t cnt;
@ -2256,10 +2218,10 @@ struct qla_hw_data {
uint32_t msix_enabled :1;
uint32_t disable_serdes :1;
uint32_t gpsc_supported :1;
uint32_t vsan_enabled :1;
uint32_t npiv_supported :1;
uint32_t fce_enabled :1;
uint32_t hw_event_marker_found:1;
uint32_t fac_supported :1;
uint32_t chip_reset_done :1;
} flags;
/* This spinlock is used to protect "io transactions", you must
@ -2277,7 +2239,7 @@ struct qla_hw_data {
#define MIN_IOBASE_LEN 0x100
/* Multi queue data structs */
device_reg_t *mqiobase;
device_reg_t __iomem *mqiobase;
uint16_t msix_count;
uint8_t mqenable;
struct req_que **req_q_map;
@ -2300,7 +2262,6 @@ struct qla_hw_data {
uint16_t max_loop_id;
uint16_t fb_rev;
uint16_t max_public_loop_ids;
uint16_t min_external_loopid; /* First external loop Id */
#define PORT_SPEED_UNKNOWN 0xFFFF
@ -2381,6 +2342,8 @@ struct qla_hw_data {
IS_QLA25XX(ha) || IS_QLA81XX(ha))
#define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \
(ha)->flags.msix_enabled)
#define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha))
#define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha))
#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)
@ -2425,6 +2388,10 @@ struct qla_hw_data {
void *sfp_data;
dma_addr_t sfp_data_dma;
uint8_t *edc_data;
dma_addr_t edc_data_dma;
uint16_t edc_data_len;
struct task_struct *dpc_thread;
uint8_t dpc_active; /* DPC routine is active */
@ -2439,6 +2406,8 @@ struct qla_hw_data {
dma_addr_t init_cb_dma;
init_cb_t *init_cb;
int init_cb_size;
dma_addr_t ex_init_cb_dma;
struct ex_init_cb_81xx *ex_init_cb;
/* These are used by mailbox operations. */
volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
@ -2453,15 +2422,6 @@ struct qla_hw_data {
struct completion mbx_cmd_comp; /* Serialize mbx access */
struct completion mbx_intr_comp; /* Used for completion notification */
uint32_t mbx_flags;
#define MBX_IN_PROGRESS BIT_0
#define MBX_BUSY BIT_1 /* Got the Access */
#define MBX_SLEEPING_ON_SEM BIT_2
#define MBX_POLLING_FOR_COMP BIT_3
#define MBX_COMPLETED BIT_4
#define MBX_TIMEDOUT BIT_5
#define MBX_ACCESS_TIMEDOUT BIT_6
/* Basic firmware related information. */
uint16_t fw_major_version;
uint16_t fw_minor_version;
@ -2473,13 +2433,15 @@ struct qla_hw_data {
#define RISC_START_ADDRESS_2100 0x1000
#define RISC_START_ADDRESS_2300 0x800
#define RISC_START_ADDRESS_2400 0x100000
uint16_t fw_xcb_count;
uint16_t fw_options[16]; /* slots: 1,2,3,10,11 */
uint8_t fw_seriallink_options[4];
uint16_t fw_seriallink_options24[4];
uint8_t mpi_version[4];
uint8_t mpi_version[3];
uint32_t mpi_capabilities;
uint8_t phy_version[3];
/* Firmware dump information. */
struct qla2xxx_fw_dump *fw_dump;
@ -2545,6 +2507,8 @@ struct qla_hw_data {
uint32_t flt_region_boot;
uint32_t flt_region_fw;
uint32_t flt_region_vpd_nvram;
uint32_t flt_region_vpd;
uint32_t flt_region_nvram;
uint32_t flt_region_npiv_conf;
/* Needed for BEACON */
@ -2613,36 +2577,19 @@ typedef struct scsi_qla_host {
#define LOOP_RESYNC_ACTIVE 5
#define LOCAL_LOOP_UPDATE 6 /* Perform a local loop update. */
#define RSCN_UPDATE 7 /* Perform an RSCN update. */
#define MAILBOX_RETRY 8
#define ISP_RESET_NEEDED 9 /* Initiate a ISP reset. */
#define FAILOVER_EVENT_NEEDED 10
#define FAILOVER_EVENT 11
#define FAILOVER_NEEDED 12
#define SCSI_RESTART_NEEDED 13 /* Processes SCSI retry queue. */
#define PORT_RESTART_NEEDED 14 /* Processes Retry queue. */
#define RESTART_QUEUES_NEEDED 15 /* Restarts the Lun queue. */
#define ABORT_QUEUES_NEEDED 16
#define RELOGIN_NEEDED 17
#define LOGIN_RETRY_NEEDED 18 /* Initiate required fabric logins. */
#define REGISTER_FC4_NEEDED 19 /* SNS FC4 registration required. */
#define ISP_ABORT_RETRY 20 /* ISP aborted. */
#define FCPORT_RESCAN_NEEDED 21 /* IO descriptor processing needed */
#define IODESC_PROCESS_NEEDED 22 /* IO descriptor processing needed */
#define IOCTL_ERROR_RECOVERY 23
#define LOOP_RESET_NEEDED 24
#define BEACON_BLINK_NEEDED 25
#define REGISTER_FDMI_NEEDED 26
#define FCPORT_UPDATE_NEEDED 27
#define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */
#define UNLOADING 29
#define NPIV_CONFIG_NEEDED 30
#define RELOGIN_NEEDED 8
#define REGISTER_FC4_NEEDED 9 /* SNS FC4 registration required. */
#define ISP_ABORT_RETRY 10 /* ISP aborted. */
#define BEACON_BLINK_NEEDED 11
#define REGISTER_FDMI_NEEDED 12
#define FCPORT_UPDATE_NEEDED 13
#define VP_DPC_NEEDED 14 /* wake up for VP dpc handling */
#define UNLOADING 15
#define NPIV_CONFIG_NEEDED 16
uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
#define DFLG_RETRY_LOCAL_DEVICES BIT_1
#define DFLG_FABRIC_DEVICES BIT_2
#define SWITCH_FOUND BIT_3
#define DFLG_NO_CABLE BIT_4
#define SWITCH_FOUND BIT_0
#define DFLG_NO_CABLE BIT_1
srb_t *status_srb; /* Status continuation entry. */
@ -2755,10 +2702,5 @@ typedef struct scsi_qla_host {
#include "qla_inline.h"
#define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr)
#define CMD_COMPL_STATUS(Cmnd) ((Cmnd)->SCp.this_residual)
#define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual)
#define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status)
#define CMD_ACTUAL_SNSLEN(Cmnd) ((Cmnd)->SCp.Message)
#define CMD_ENTRY_STATUS(Cmnd) ((Cmnd)->SCp.have_data_in)
#endif

View file

@ -71,7 +71,7 @@ qla2x00_dfs_fce_open(struct inode *inode, struct file *file)
mutex_unlock(&ha->fce_mutex);
out:
return single_open(file, qla2x00_dfs_fce_show, ha);
return single_open(file, qla2x00_dfs_fce_show, vha);
}
static int
@ -145,7 +145,7 @@ create_dir:
atomic_inc(&qla2x00_dfs_root_count);
create_nodes:
ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, ha,
ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha,
&dfs_fce_ops);
if (!ha->dfs_fce) {
qla_printk(KERN_NOTICE, ha,

View file

@ -1403,6 +1403,21 @@ struct access_chip_rsp_84xx {
#define MBA_IDC_TIME_EXT 0x8102
#define MBC_IDC_ACK 0x101
#define MBC_RESTART_MPI_FW 0x3d
#define MBC_FLASH_ACCESS_CTRL 0x3e /* Control flash access. */
/* Flash access control option field bit definitions */
#define FAC_OPT_FORCE_SEMAPHORE BIT_15
#define FAC_OPT_REQUESTOR_ID BIT_14
#define FAC_OPT_CMD_SUBCODE 0xff
/* Flash access control command subcodes */
#define FAC_OPT_CMD_WRITE_PROTECT 0x00
#define FAC_OPT_CMD_WRITE_ENABLE 0x01
#define FAC_OPT_CMD_ERASE_SECTOR 0x02
#define FAC_OPT_CMD_LOCK_SEMAPHORE 0x03
#define FAC_OPT_CMD_UNLOCK_SEMAPHORE 0x04
#define FAC_OPT_CMD_GET_SECTOR_SIZE 0x05
struct nvram_81xx {
/* NVRAM header. */
@ -1440,7 +1455,17 @@ struct nvram_81xx {
uint16_t reserved_6[24];
/* Offset 128. */
uint16_t reserved_7[64];
uint16_t ex_version;
uint8_t prio_fcf_matching_flags;
uint8_t reserved_6_1[3];
uint16_t pri_fcf_vlan_id;
uint8_t pri_fcf_fabric_name[8];
uint16_t reserved_6_2[7];
uint8_t spma_mac_addr[6];
uint16_t reserved_6_3[14];
/* Offset 192. */
uint16_t reserved_7[32];
/*
* BIT 0 = Enable spinup delay
@ -1664,6 +1689,17 @@ struct mid_init_cb_81xx {
struct mid_conf_entry_24xx entries[MAX_MULTI_ID_FABRIC];
};
struct ex_init_cb_81xx {
uint16_t ex_version;
uint8_t prio_fcf_matching_flags;
uint8_t reserved_1[3];
uint16_t pri_fcf_vlan_id;
uint8_t pri_fcf_fabric_name[8];
uint16_t reserved_2[7];
uint8_t spma_mac_addr[6];
uint16_t reserved_3[14];
};
#define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000
#define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000
@ -1672,6 +1708,10 @@ struct mid_init_cb_81xx {
#define FA_RISC_CODE_ADDR_81 0xA0000
#define FA_FW_AREA_ADDR_81 0xC0000
#define FA_VPD_NVRAM_ADDR_81 0xD0000
#define FA_VPD0_ADDR_81 0xD0000
#define FA_VPD1_ADDR_81 0xD0400
#define FA_NVRAM0_ADDR_81 0xD0080
#define FA_NVRAM1_ADDR_81 0xD0480
#define FA_FEATURE_ADDR_81 0xD4000
#define FA_FLASH_DESCR_ADDR_81 0xD8000
#define FA_FLASH_LAYOUT_ADDR_81 0xD8400

View file

@ -73,6 +73,7 @@ extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
fc_host_event_code, u32);
extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
extern void qla2x00_abort_fcport_cmds(fc_port_t *);
extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
@ -82,7 +83,7 @@ extern void qla2x00_relogin(struct scsi_qla_host *);
/*
* Global Functions in qla_mid.c source file.
*/
extern struct scsi_host_template qla24xx_driver_template;
extern struct scsi_host_template qla2xxx_driver_template;
extern struct scsi_transport_template *qla2xxx_transport_vport_template;
extern void qla2x00_timer(scsi_qla_host_t *);
extern void qla2x00_start_timer(scsi_qla_host_t *, void *, unsigned long);
@ -110,6 +111,7 @@ extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
extern int qla2x00_wait_for_chip_reset(scsi_qla_host_t *);
extern void qla2xxx_wake_dpc(struct scsi_qla_host *);
extern void qla2x00_alert_all_vps(struct rsp_que *, uint16_t *);
@ -144,8 +146,8 @@ extern int
qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
extern void
qla2x00_get_fw_version(scsi_qla_host_t *, uint16_t *,
uint16_t *, uint16_t *, uint16_t *, uint32_t *, uint8_t *, uint32_t *);
qla2x00_get_fw_version(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *,
uint16_t *, uint32_t *, uint8_t *, uint32_t *, uint8_t *);
extern int
qla2x00_get_fw_options(scsi_qla_host_t *, uint16_t *);
@ -262,6 +264,14 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *, uint64_t *, uint64_t *);
extern int
qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
extern int
qla2x00_read_edc(scsi_qla_host_t *, uint16_t, uint16_t, dma_addr_t,
uint8_t *, uint16_t, uint16_t);
extern int
qla2x00_write_edc(scsi_qla_host_t *, uint16_t, uint16_t, dma_addr_t,
uint8_t *, uint16_t, uint16_t);
extern int
qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
@ -269,6 +279,15 @@ extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
extern int qla81xx_idc_ack(scsi_qla_host_t *, uint16_t *);
extern int
qla81xx_fac_get_sector_size(scsi_qla_host_t *, uint32_t *);
extern int
qla81xx_fac_do_write_enable(scsi_qla_host_t *, int);
extern int
qla81xx_fac_erase_sector(scsi_qla_host_t *, uint32_t, uint32_t);
/*
* Global Function Prototypes in qla_isr.c source file.
*/

View file

@ -20,7 +20,6 @@
* QLogic ISP2x00 Hardware Support Function Prototypes.
*/
static int qla2x00_isp_firmware(scsi_qla_host_t *);
static void qla2x00_resize_request_q(scsi_qla_host_t *);
static int qla2x00_setup_chip(scsi_qla_host_t *);
static int qla2x00_init_rings(scsi_qla_host_t *);
static int qla2x00_fw_ready(scsi_qla_host_t *);
@ -61,8 +60,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
int rval;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
/* Clear adapter flags. */
vha->flags.online = 0;
ha->flags.chip_reset_done = 0;
vha->flags.reset_active = 0;
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
atomic_set(&vha->loop_state, LOOP_DOWN);
@ -70,7 +71,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
vha->dpc_flags = 0;
vha->flags.management_server_logged_in = 0;
vha->marker_needed = 0;
ha->mbx_flags = 0;
ha->isp_abort_cnt = 0;
ha->beacon_blink_led = 0;
set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
@ -131,6 +131,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
}
}
rval = qla2x00_init_rings(vha);
ha->flags.chip_reset_done = 1;
return (rval);
}
@ -512,7 +513,6 @@ qla2x00_reset_chip(scsi_qla_host_t *vha)
static inline void
qla24xx_reset_risc(scsi_qla_host_t *vha)
{
int hw_evt = 0;
unsigned long flags = 0;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
@ -542,8 +542,6 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
d2 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
barrier();
}
if (cnt == 0)
hw_evt = 1;
/* Wait for soft-reset to complete. */
d2 = RD_REG_DWORD(&reg->ctrl_status);
@ -816,7 +814,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n",
FCE_SIZE / 1024);
fce_size = sizeof(struct qla2xxx_fce_chain) + EFT_SIZE;
fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
ha->flags.fce_enabled = 1;
ha->fce_dma = tc_dma;
ha->fce = tc;
@ -893,62 +891,6 @@ cont_alloc:
htonl(offsetof(struct qla2xxx_fw_dump, isp));
}
/**
* qla2x00_resize_request_q() - Resize request queue given available ISP memory.
* @ha: HA context
*
* Returns 0 on success.
*/
static void
qla2x00_resize_request_q(scsi_qla_host_t *vha)
{
int rval;
uint16_t fw_iocb_cnt = 0;
uint16_t request_q_length = REQUEST_ENTRY_CNT_2XXX_EXT_MEM;
dma_addr_t request_dma;
request_t *request_ring;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
/* Valid only on recent ISPs. */
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return;
/* Retrieve IOCB counts available to the firmware. */
rval = qla2x00_get_resource_cnts(vha, NULL, NULL, NULL, &fw_iocb_cnt,
&ha->max_npiv_vports);
if (rval)
return;
/* No point in continuing if current settings are sufficient. */
if (fw_iocb_cnt < 1024)
return;
if (req->length >= request_q_length)
return;
/* Attempt to claim larger area for request queue. */
request_ring = dma_alloc_coherent(&ha->pdev->dev,
(request_q_length + 1) * sizeof(request_t), &request_dma,
GFP_KERNEL);
if (request_ring == NULL)
return;
/* Resize successful, report extensions. */
qla_printk(KERN_INFO, ha, "Extended memory detected (%d KB)...\n",
(ha->fw_memory_size + 1) / 1024);
qla_printk(KERN_INFO, ha, "Resizing request queue depth "
"(%d -> %d)...\n", req->length, request_q_length);
/* Clear old allocations. */
dma_free_coherent(&ha->pdev->dev,
(req->length + 1) * sizeof(request_t), req->ring,
req->dma);
/* Begin using larger queue. */
req->length = request_q_length;
req->ring = request_ring;
req->dma = request_dma;
}
/**
* qla2x00_setup_chip() - Load and start RISC firmware.
* @ha: HA context
@ -963,6 +905,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
unsigned long flags;
uint16_t fw_major_version;
if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
/* Disable SRAM, Instruction RAM and GP RAM parity. */
@ -986,13 +929,15 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
rval = qla2x00_execute_fw(vha, srisc_address);
/* Retrieve firmware information. */
if (rval == QLA_SUCCESS && ha->fw_major_version == 0) {
if (rval == QLA_SUCCESS) {
fw_major_version = ha->fw_major_version;
qla2x00_get_fw_version(vha,
&ha->fw_major_version,
&ha->fw_minor_version,
&ha->fw_subminor_version,
&ha->fw_attributes, &ha->fw_memory_size,
ha->mpi_version, &ha->mpi_capabilities);
ha->mpi_version, &ha->mpi_capabilities,
ha->phy_version);
ha->flags.npiv_supported = 0;
if (IS_QLA2XXX_MIDTYPE(ha) &&
(ha->fw_attributes & BIT_2)) {
@ -1003,9 +948,11 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
ha->max_npiv_vports =
MIN_MULTI_ID_FABRIC - 1;
}
qla2x00_resize_request_q(vha);
qla2x00_get_resource_cnts(vha, NULL,
&ha->fw_xcb_count, NULL, NULL,
&ha->max_npiv_vports);
if (ql2xallocfwdump)
if (!fw_major_version && ql2xallocfwdump)
qla2x00_alloc_fw_dump(vha);
}
} else {
@ -1028,6 +975,21 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) {
uint32_t size;
rval = qla81xx_fac_get_sector_size(vha, &size);
if (rval == QLA_SUCCESS) {
ha->flags.fac_supported = 1;
ha->fdt_block_size = size << 2;
} else {
qla_printk(KERN_ERR, ha,
"Unsupported FAC firmware (%d.%02d.%02d).\n",
ha->fw_major_version, ha->fw_minor_version,
ha->fw_subminor_version);
}
}
if (rval) {
DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n",
vha->host_no));
@ -1314,8 +1276,11 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports);
}
mid_init_cb->options = __constant_cpu_to_le16(BIT_1);
if (IS_FWI2_CAPABLE(ha)) {
mid_init_cb->options = __constant_cpu_to_le16(BIT_1);
mid_init_cb->init_cb.execution_throttle =
cpu_to_le16(ha->fw_xcb_count);
}
rval = qla2x00_init_firmware(vha, ha->init_cb_size);
if (rval) {
@ -1989,7 +1954,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
fcport->port_type = FCT_UNKNOWN;
fcport->loop_id = FC_NO_LOOP_ID;
atomic_set(&fcport->state, FCS_UNCONFIGURED);
fcport->flags = FCF_RLC_SUPPORT;
fcport->supported_classes = FC_COS_UNSPECIFIED;
return fcport;
@ -2171,7 +2135,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
vha->host_no, fcport->loop_id));
atomic_set(&fcport->state, FCS_DEVICE_LOST);
fcport->flags &= ~FCF_FARP_DONE;
}
}
@ -2228,8 +2191,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
WWN_SIZE))
continue;
fcport->flags &= ~(FCF_FABRIC_DEVICE |
FCF_PERSISTENT_BOUND);
fcport->flags &= ~FCF_FABRIC_DEVICE;
fcport->loop_id = new_fcport->loop_id;
fcport->port_type = new_fcport->port_type;
fcport->d_id.b24 = new_fcport->d_id.b24;
@ -2242,7 +2204,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
if (!found) {
/* New device, add to fcports list. */
new_fcport->flags &= ~FCF_PERSISTENT_BOUND;
if (vha->vp_idx) {
new_fcport->vha = vha;
new_fcport->vp_idx = vha->vp_idx;
@ -2275,11 +2236,6 @@ cleanup_allocation:
"rval=%x\n", vha->host_no, rval));
}
if (found_devs) {
vha->device_flags |= DFLG_LOCAL_DEVICES;
vha->device_flags &= ~DFLG_RETRY_LOCAL_DEVICES;
}
return (rval);
}
@ -2765,7 +2721,6 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
fcport->loop_id = FC_NO_LOOP_ID;
fcport->flags |= (FCF_FABRIC_DEVICE |
FCF_LOGIN_NEEDED);
fcport->flags &= ~FCF_PERSISTENT_BOUND;
break;
}
@ -2808,9 +2763,6 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
kfree(swl);
kfree(new_fcport);
if (!list_empty(new_fcports))
vha->device_flags |= DFLG_FABRIC_DEVICES;
return (rval);
}
@ -2993,7 +2945,6 @@ qla2x00_device_resync(scsi_qla_host_t *vha)
0, 0);
}
}
fcport->flags &= ~FCF_FARP_DONE;
}
}
return (rval);
@ -3302,6 +3253,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
if (vha->flags.online) {
vha->flags.online = 0;
ha->flags.chip_reset_done = 0;
clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
ha->qla_stats.total_isp_aborts++;
@ -3451,6 +3403,7 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
if (!status && !(status = qla2x00_init_rings(vha))) {
clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
ha->flags.chip_reset_done = 1;
/* Initialize the queues in use */
qla25xx_init_queues(ha);
@ -4338,23 +4291,17 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
/* Determine NVRAM starting address. */
ha->nvram_size = sizeof(struct nvram_81xx);
ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
ha->vpd_size = FA_NVRAM_VPD_SIZE;
ha->vpd_base = FA_NVRAM_VPD0_ADDR;
if (PCI_FUNC(ha->pdev->devfn) & 1) {
ha->nvram_base = FA_NVRAM_FUNC1_ADDR;
ha->vpd_base = FA_NVRAM_VPD1_ADDR;
}
/* Get VPD data into cache */
ha->vpd = ha->nvram + VPD_OFFSET;
ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd,
ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4);
ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
ha->vpd_size);
/* Get NVRAM data into cache and calculate checksum. */
dptr = (uint32_t *)nv;
ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base,
ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
ha->nvram_size);
dptr = (uint32_t *)nv;
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
chksum += le32_to_cpu(*dptr++);
@ -4452,6 +4399,9 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
icb->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn);
}
/* Use extended-initialization control block. */
memcpy(ha->ex_init_cb, &nv->ex_version, sizeof(*ha->ex_init_cb));
/*
* Setup driver NVRAM options.
*/

View file

@ -776,7 +776,7 @@ qla24xx_start_scsi(srb_t *sp)
req_cnt = qla24xx_calc_iocbs(tot_dsds);
if (req->cnt < (req_cnt + 2)) {
cnt = ha->isp_ops->rd_req_reg(ha, req->id);
cnt = RD_REG_DWORD_RELAXED(req->req_q_out);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
@ -836,7 +836,8 @@ qla24xx_start_scsi(srb_t *sp)
sp->flags |= SRB_DMA_VALID;
/* Set chip new ring index. */
ha->isp_ops->wrt_req_reg(ha, req->id, req->ring_index);
WRT_REG_DWORD(req->req_q_in, req->ring_index);
RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr);
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (vha->flags.process_response_queue &&
@ -854,35 +855,3 @@ queuing_error:
return QLA_FUNCTION_FAILED;
}
uint16_t
qla24xx_rd_req_reg(struct qla_hw_data *ha, uint16_t id)
{
device_reg_t __iomem *reg = (void *) ha->iobase;
return RD_REG_DWORD_RELAXED(&reg->isp24.req_q_out);
}
uint16_t
qla25xx_rd_req_reg(struct qla_hw_data *ha, uint16_t id)
{
device_reg_t __iomem *reg = (void *) ha->mqiobase + QLA_QUE_PAGE * id;
return RD_REG_DWORD_RELAXED(&reg->isp25mq.req_q_out);
}
void
qla24xx_wrt_req_reg(struct qla_hw_data *ha, uint16_t id, uint16_t index)
{
device_reg_t __iomem *reg = (void *) ha->iobase;
WRT_REG_DWORD(&reg->isp24.req_q_in, index);
RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in);
}
void
qla25xx_wrt_req_reg(struct qla_hw_data *ha, uint16_t id, uint16_t index)
{
device_reg_t __iomem *reg = (void *) ha->mqiobase + QLA_QUE_PAGE * id;
struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp;
WRT_REG_DWORD(&reg->isp25mq.req_q_in, index);
RD_REG_DWORD(&ioreg->hccr); /* PCI posting */
}

View file

@ -852,9 +852,6 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
/* Free outstanding command slot. */
req->outstanding_cmds[index] = NULL;
CMD_COMPL_STATUS(sp->cmd) = 0L;
CMD_SCSI_STATUS(sp->cmd) = 0L;
/* Save ISP completion status */
sp->cmd->result = DID_OK << 16;
@ -955,7 +952,6 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
if (sense_len >= SCSI_SENSE_BUFFERSIZE)
sense_len = SCSI_SENSE_BUFFERSIZE;
CMD_ACTUAL_SNSLEN(cp) = sense_len;
sp->request_sense_length = sense_len;
sp->request_sense_ptr = cp->sense_buffer;
if (sp->request_sense_length > 32)
@ -973,8 +969,7 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
cp->device->channel, cp->device->id, cp->device->lun, cp,
cp->serial_number));
if (sense_len)
DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
CMD_ACTUAL_SNSLEN(cp)));
DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len));
}
/**
@ -1043,9 +1038,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
}
lscsi_status = scsi_status & STATUS_MASK;
CMD_ENTRY_STATUS(cp) = sts->entry_status;
CMD_COMPL_STATUS(cp) = comp_status;
CMD_SCSI_STATUS(cp) = scsi_status;
fcport = sp->fcport;
@ -1104,7 +1096,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
resid = resid_len;
scsi_set_resid(cp, resid);
CMD_RESID_LEN(cp) = resid;
if (!lscsi_status &&
((unsigned)(scsi_bufflen(cp) - resid) <
@ -1160,7 +1151,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
if (scsi_status & SS_RESIDUAL_UNDER) {
scsi_set_resid(cp, resid);
CMD_RESID_LEN(cp) = resid;
} else {
DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d) UNDERRUN status detected "
@ -1499,7 +1489,6 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
void
qla24xx_process_response_queue(struct rsp_que *rsp)
{
struct qla_hw_data *ha = rsp->hw;
struct sts_entry_24xx *pkt;
struct scsi_qla_host *vha;
@ -1553,7 +1542,7 @@ qla24xx_process_response_queue(struct rsp_que *rsp)
}
/* Adjust ring index */
ha->isp_ops->wrt_rsp_reg(ha, rsp->id, rsp->ring_index);
WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
}
static void
@ -2029,7 +2018,7 @@ skip_msix:
skip_msi:
ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, rsp);
IRQF_SHARED, QLA2XXX_DRIVER_NAME, rsp);
if (ret) {
qla_printk(KERN_WARNING, ha,
"Failed to reserve interrupt %d already in use.\n",
@ -2117,18 +2106,3 @@ int qla25xx_request_irq(struct rsp_que *rsp)
msix->rsp = rsp;
return ret;
}
void
qla25xx_wrt_rsp_reg(struct qla_hw_data *ha, uint16_t id, uint16_t index)
{
device_reg_t __iomem *reg = (void *) ha->mqiobase + QLA_QUE_PAGE * id;
WRT_REG_DWORD(&reg->isp25mq.rsp_q_out, index);
}
void
qla24xx_wrt_rsp_reg(struct qla_hw_data *ha, uint16_t id, uint16_t index)
{
device_reg_t __iomem *reg = (void *) ha->iobase;
WRT_REG_DWORD(&reg->isp24.rsp_q_out, index);
}

View file

@ -45,6 +45,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
if (ha->pdev->error_state > pci_channel_io_frozen)
return QLA_FUNCTION_TIMEOUT;
reg = ha->iobase;
io_lock_on = base_vha->flags.init_done;
@ -408,7 +411,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
void
qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
uint16_t *subminor, uint16_t *attributes, uint32_t *memory, uint8_t *mpi,
uint32_t *mpi_caps)
uint32_t *mpi_caps, uint8_t *phy)
{
int rval;
mbx_cmd_t mc;
@ -420,7 +423,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
mcp->out_mb = MBX_0;
mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
if (IS_QLA81XX(vha->hw))
mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8;
mcp->flags = 0;
mcp->tov = MBX_TOV_SECONDS;
rval = qla2x00_mailbox_command(vha, mcp);
@ -435,11 +438,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
else
*memory = (mcp->mb[5] << 16) | mcp->mb[4];
if (IS_QLA81XX(vha->hw)) {
mpi[0] = mcp->mb[10] >> 8;
mpi[1] = mcp->mb[10] & 0xff;
mpi[2] = mcp->mb[11] >> 8;
mpi[3] = mcp->mb[11] & 0xff;
mpi[0] = mcp->mb[10] & 0xff;
mpi[1] = mcp->mb[11] >> 8;
mpi[2] = mcp->mb[11] & 0xff;
*mpi_caps = (mcp->mb[12] << 16) | mcp->mb[13];
phy[0] = mcp->mb[8] & 0xff;
phy[1] = mcp->mb[9] >> 8;
phy[2] = mcp->mb[9] & 0xff;
}
if (rval != QLA_SUCCESS) {
@ -1043,14 +1048,22 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
else
mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
mcp->mb[1] = 0;
mcp->mb[2] = MSW(ha->init_cb_dma);
mcp->mb[3] = LSW(ha->init_cb_dma);
mcp->mb[4] = 0;
mcp->mb[5] = 0;
mcp->mb[6] = MSW(MSD(ha->init_cb_dma));
mcp->mb[7] = LSW(MSD(ha->init_cb_dma));
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
mcp->in_mb = MBX_5|MBX_4|MBX_0;
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
if (IS_QLA81XX(ha) && ha->ex_init_cb->ex_version) {
mcp->mb[1] = BIT_0;
mcp->mb[10] = MSW(ha->ex_init_cb_dma);
mcp->mb[11] = LSW(ha->ex_init_cb_dma);
mcp->mb[12] = MSW(MSD(ha->ex_init_cb_dma));
mcp->mb[13] = LSW(MSD(ha->ex_init_cb_dma));
mcp->mb[14] = sizeof(*ha->ex_init_cb);
mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10;
}
mcp->in_mb = MBX_0;
mcp->buf_size = size;
mcp->flags = MBX_DMA_OUT;
mcp->tov = MBX_TOV_SECONDS;
@ -1187,10 +1200,6 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
fcport->d_id.b.al_pa = pd->port_id[2];
fcport->d_id.b.rsvd_1 = 0;
/* Check for device require authentication. */
pd->common_features & BIT_5 ? (fcport->flags |= FCF_AUTH_REQ) :
(fcport->flags &= ~FCF_AUTH_REQ);
/* If not target must be initiator or unknown type. */
if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
fcport->port_type = FCT_INITIATOR;
@ -3218,3 +3227,204 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
return rval;
}
int
qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
if (!IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
mcp->mb[1] = FAC_OPT_CMD_GET_SECTOR_SIZE;
mcp->out_mb = MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
__func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
*sector_size = mcp->mb[1];
}
return rval;
}
int
qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
if (!IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE :
FAC_OPT_CMD_WRITE_PROTECT;
mcp->out_mb = MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
__func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
}
return rval;
}
int
qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
if (!IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR;
mcp->mb[2] = LSW(start);
mcp->mb[3] = MSW(start);
mcp->mb[4] = LSW(finish);
mcp->mb[5] = MSW(finish);
mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_2|MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
"mb[2]=%x.\n", __func__, vha->host_no, rval, mcp->mb[0],
mcp->mb[1], mcp->mb[2]));
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
}
return rval;
}
int
qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
{
int rval = 0;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
mcp->mb[0] = MBC_RESTART_MPI_FW;
mcp->out_mb = MBX_0;
mcp->in_mb = MBX_0|MBX_1;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=0x%x mb[1]=0x%x.\n",
__func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
}
return rval;
}
int
qla2x00_read_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
dma_addr_t sfp_dma, uint8_t *sfp, uint16_t len, uint16_t opt)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
mcp->mb[0] = MBC_READ_SFP;
mcp->mb[1] = dev;
mcp->mb[2] = MSW(sfp_dma);
mcp->mb[3] = LSW(sfp_dma);
mcp->mb[6] = MSW(MSD(sfp_dma));
mcp->mb[7] = LSW(MSD(sfp_dma));
mcp->mb[8] = len;
mcp->mb[9] = adr;
mcp->mb[10] = opt;
mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (opt & BIT_0)
if (sfp)
*sfp = mcp->mb[8];
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
vha->host_no, rval, mcp->mb[0]));
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
}
return rval;
}
int
qla2x00_write_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
dma_addr_t sfp_dma, uint8_t *sfp, uint16_t len, uint16_t opt)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
if (opt & BIT_0)
if (sfp)
len = *sfp;
mcp->mb[0] = MBC_WRITE_SFP;
mcp->mb[1] = dev;
mcp->mb[2] = MSW(sfp_dma);
mcp->mb[3] = LSW(sfp_dma);
mcp->mb[6] = MSW(MSD(sfp_dma));
mcp->mb[7] = LSW(MSD(sfp_dma));
mcp->mb[8] = len;
mcp->mb[9] = adr;
mcp->mb[10] = opt;
mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
vha->host_no, rval, mcp->mb[0]));
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
}
return rval;
}

View file

@ -359,7 +359,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost);
struct qla_hw_data *ha = base_vha->hw;
scsi_qla_host_t *vha;
struct scsi_host_template *sht = &qla24xx_driver_template;
struct scsi_host_template *sht = &qla2xxx_driver_template;
struct Scsi_Host *host;
vha = qla2x00_create_host(sht, ha);
@ -584,6 +584,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
struct req_que *req = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
uint16_t que_id = 0;
device_reg_t __iomem *reg;
req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
if (req == NULL) {
@ -631,6 +632,9 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req->ring_index = 0;
req->cnt = req->length;
req->id = que_id;
reg = ISP_QUE_REG(ha, que_id);
req->req_q_in = &reg->isp25mq.req_q_in;
req->req_q_out = &reg->isp25mq.req_q_out;
req->max_q_depth = ha->req_q_map[0]->max_q_depth;
mutex_unlock(&ha->vport_lock);
@ -658,7 +662,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
int ret = 0;
struct rsp_que *rsp = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
uint16_t que_id = 0;;
uint16_t que_id = 0;
device_reg_t __iomem *reg;
rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
if (rsp == NULL) {
@ -706,6 +711,9 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
rsp->ring_ptr = rsp->ring;
rsp->ring_index = 0;
rsp->id = que_id;
reg = ISP_QUE_REG(ha, que_id);
rsp->rsp_q_in = &reg->isp25mq.rsp_q_in;
rsp->rsp_q_out = &reg->isp25mq.rsp_q_out;
mutex_unlock(&ha->vport_lock);
ret = qla25xx_request_irq(rsp);

View file

@ -104,9 +104,7 @@ static int qla2xxx_slave_alloc(struct scsi_device *);
static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
static void qla2xxx_scan_start(struct Scsi_Host *);
static void qla2xxx_slave_destroy(struct scsi_device *);
static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
void (*fn)(struct scsi_cmnd *));
static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
static int qla2xxx_queuecommand(struct scsi_cmnd *cmd,
void (*fn)(struct scsi_cmnd *));
static int qla2xxx_eh_abort(struct scsi_cmnd *);
static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
@ -117,42 +115,10 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
static int qla2x00_change_queue_depth(struct scsi_device *, int);
static int qla2x00_change_queue_type(struct scsi_device *, int);
static struct scsi_host_template qla2x00_driver_template = {
struct scsi_host_template qla2xxx_driver_template = {
.module = THIS_MODULE,
.name = QLA2XXX_DRIVER_NAME,
.queuecommand = qla2x00_queuecommand,
.eh_abort_handler = qla2xxx_eh_abort,
.eh_device_reset_handler = qla2xxx_eh_device_reset,
.eh_target_reset_handler = qla2xxx_eh_target_reset,
.eh_bus_reset_handler = qla2xxx_eh_bus_reset,
.eh_host_reset_handler = qla2xxx_eh_host_reset,
.slave_configure = qla2xxx_slave_configure,
.slave_alloc = qla2xxx_slave_alloc,
.slave_destroy = qla2xxx_slave_destroy,
.scan_finished = qla2xxx_scan_finished,
.scan_start = qla2xxx_scan_start,
.change_queue_depth = qla2x00_change_queue_depth,
.change_queue_type = qla2x00_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = SG_ALL,
/*
* The RISC allows for each command to transfer (2^32-1) bytes of data,
* which equates to 0x800000 sectors.
*/
.max_sectors = 0xFFFF,
.shost_attrs = qla2x00_host_attrs,
};
struct scsi_host_template qla24xx_driver_template = {
.module = THIS_MODULE,
.name = QLA2XXX_DRIVER_NAME,
.queuecommand = qla24xx_queuecommand,
.queuecommand = qla2xxx_queuecommand,
.eh_abort_handler = qla2xxx_eh_abort,
.eh_device_reset_handler = qla2xxx_eh_device_reset,
@ -430,73 +396,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
}
static int
qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
struct qla_hw_data *ha = vha->hw;
srb_t *sp;
int rval;
if (unlikely(pci_channel_offline(ha->pdev))) {
cmd->result = DID_REQUEUE << 16;
goto qc_fail_command;
}
rval = fc_remote_port_chkready(rport);
if (rval) {
cmd->result = rval;
goto qc_fail_command;
}
/* Close window on fcport/rport state-transitioning. */
if (fcport->drport)
goto qc_target_busy;
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&vha->loop_state) == LOOP_DEAD) {
cmd->result = DID_NO_CONNECT << 16;
goto qc_fail_command;
}
goto qc_target_busy;
}
spin_unlock_irq(vha->host->host_lock);
sp = qla2x00_get_new_sp(vha, fcport, cmd, done);
if (!sp)
goto qc_host_busy_lock;
rval = ha->isp_ops->start_scsi(sp);
if (rval != QLA_SUCCESS)
goto qc_host_busy_free_sp;
spin_lock_irq(vha->host->host_lock);
return 0;
qc_host_busy_free_sp:
qla2x00_sp_free_dma(sp);
mempool_free(sp, ha->srb_mempool);
qc_host_busy_lock:
spin_lock_irq(vha->host->host_lock);
return SCSI_MLQUEUE_HOST_BUSY;
qc_target_busy:
return SCSI_MLQUEUE_TARGET_BUSY;
qc_fail_command:
done(cmd);
return 0;
}
static int
qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
@ -507,7 +407,10 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
int rval;
if (unlikely(pci_channel_offline(ha->pdev))) {
cmd->result = DID_REQUEUE << 16;
if (ha->pdev->error_state == pci_channel_io_frozen)
cmd->result = DID_REQUEUE << 16;
else
cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
@ -635,6 +538,34 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
return (return_status);
}
int
qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
{
int return_status;
unsigned long wait_reset;
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ);
while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
ha->dpc_active) && time_before(jiffies, wait_reset)) {
msleep(1000);
if (!test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) &&
ha->flags.chip_reset_done)
break;
}
if (ha->flags.chip_reset_done)
return_status = QLA_SUCCESS;
else
return_status = QLA_FUNCTION_FAILED;
return return_status;
}
/*
* qla2x00_wait_for_loop_ready
* Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
@ -1163,7 +1094,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
continue;
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
sp = req->outstanding_cmds[cnt];
if (sp && sp->fcport->vha == vha) {
if (sp) {
req->outstanding_cmds[cnt] = NULL;
sp->cmd->result = res;
qla2x00_sp_compl(ha, sp);
@ -1351,9 +1282,6 @@ static struct isp_operations qla2100_isp_ops = {
.write_optrom = qla2x00_write_optrom_data,
.get_flash_version = qla2x00_get_flash_version,
.start_scsi = qla2x00_start_scsi,
.wrt_req_reg = NULL,
.wrt_rsp_reg = NULL,
.rd_req_reg = NULL,
};
static struct isp_operations qla2300_isp_ops = {
@ -1389,9 +1317,6 @@ static struct isp_operations qla2300_isp_ops = {
.write_optrom = qla2x00_write_optrom_data,
.get_flash_version = qla2x00_get_flash_version,
.start_scsi = qla2x00_start_scsi,
.wrt_req_reg = NULL,
.wrt_rsp_reg = NULL,
.rd_req_reg = NULL,
};
static struct isp_operations qla24xx_isp_ops = {
@ -1427,9 +1352,6 @@ static struct isp_operations qla24xx_isp_ops = {
.write_optrom = qla24xx_write_optrom_data,
.get_flash_version = qla24xx_get_flash_version,
.start_scsi = qla24xx_start_scsi,
.wrt_req_reg = qla24xx_wrt_req_reg,
.wrt_rsp_reg = qla24xx_wrt_rsp_reg,
.rd_req_reg = qla24xx_rd_req_reg,
};
static struct isp_operations qla25xx_isp_ops = {
@ -1465,9 +1387,6 @@ static struct isp_operations qla25xx_isp_ops = {
.write_optrom = qla24xx_write_optrom_data,
.get_flash_version = qla24xx_get_flash_version,
.start_scsi = qla24xx_start_scsi,
.wrt_req_reg = qla24xx_wrt_req_reg,
.wrt_rsp_reg = qla24xx_wrt_rsp_reg,
.rd_req_reg = qla24xx_rd_req_reg,
};
static struct isp_operations qla81xx_isp_ops = {
@ -1493,8 +1412,8 @@ static struct isp_operations qla81xx_isp_ops = {
.build_iocbs = NULL,
.prep_ms_iocb = qla24xx_prep_ms_iocb,
.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb,
.read_nvram = qla25xx_read_nvram_data,
.write_nvram = qla25xx_write_nvram_data,
.read_nvram = NULL,
.write_nvram = NULL,
.fw_dump = qla81xx_fw_dump,
.beacon_on = qla24xx_beacon_on,
.beacon_off = qla24xx_beacon_off,
@ -1503,9 +1422,6 @@ static struct isp_operations qla81xx_isp_ops = {
.write_optrom = qla24xx_write_optrom_data,
.get_flash_version = qla24xx_get_flash_version,
.start_scsi = qla24xx_start_scsi,
.wrt_req_reg = qla24xx_wrt_req_reg,
.wrt_rsp_reg = qla24xx_wrt_rsp_reg,
.rd_req_reg = qla24xx_rd_req_reg,
};
static inline void
@ -1727,7 +1643,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
struct rsp_que *rsp = NULL;
bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
sht = &qla2x00_driver_template;
sht = &qla2xxx_driver_template;
if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
@ -1736,7 +1652,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001) {
bars = pci_select_bars(pdev, IORESOURCE_MEM);
sht = &qla24xx_driver_template;
mem_only = 1;
}
@ -1927,10 +1842,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->rsp_q_map[0] = rsp;
ha->req_q_map[0] = req;
/* FWI2-capable only. */
req->req_q_in = &ha->iobase->isp24.req_q_in;
req->req_q_out = &ha->iobase->isp24.req_q_out;
rsp->rsp_q_in = &ha->iobase->isp24.rsp_q_in;
rsp->rsp_q_out = &ha->iobase->isp24.rsp_q_out;
if (ha->mqenable) {
ha->isp_ops->wrt_req_reg = qla25xx_wrt_req_reg;
ha->isp_ops->wrt_rsp_reg = qla25xx_wrt_rsp_reg;
ha->isp_ops->rd_req_reg = qla25xx_rd_req_reg;
req->req_q_in = &ha->mqiobase->isp25mq.req_q_in;
req->req_q_out = &ha->mqiobase->isp25mq.req_q_out;
rsp->rsp_q_in = &ha->mqiobase->isp25mq.rsp_q_in;
rsp->rsp_q_out = &ha->mqiobase->isp25mq.rsp_q_out;
}
if (qla2x00_initialize_adapter(base_vha)) {
@ -2000,6 +1921,16 @@ probe_init_failed:
ha->max_queues = 0;
probe_failed:
if (base_vha->timer_active)
qla2x00_stop_timer(base_vha);
base_vha->flags.online = 0;
if (ha->dpc_thread) {
struct task_struct *t = ha->dpc_thread;
ha->dpc_thread = NULL;
kthread_stop(t);
}
qla2x00_free_device(base_vha);
scsi_host_put(base_vha->host);
@ -2033,10 +1964,30 @@ qla2x00_remove_one(struct pci_dev *pdev)
set_bit(UNLOADING, &base_vha->dpc_flags);
qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
qla2x00_dfs_remove(base_vha);
qla84xx_put_chip(base_vha);
/* Disable timer */
if (base_vha->timer_active)
qla2x00_stop_timer(base_vha);
base_vha->flags.online = 0;
/* Kill the kernel thread for this host */
if (ha->dpc_thread) {
struct task_struct *t = ha->dpc_thread;
/*
* qla2xxx_wake_dpc checks for ->dpc_thread
* so we need to zero it out.
*/
ha->dpc_thread = NULL;
kthread_stop(t);
}
qla2x00_free_sysfs_attr(base_vha);
fc_remove_host(base_vha->host);
@ -2065,25 +2016,6 @@ static void
qla2x00_free_device(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
/* Disable timer */
if (vha->timer_active)
qla2x00_stop_timer(vha);
vha->flags.online = 0;
/* Kill the kernel thread for this host */
if (ha->dpc_thread) {
struct task_struct *t = ha->dpc_thread;
/*
* qla2xxx_wake_dpc checks for ->dpc_thread
* so we need to zero it out.
*/
ha->dpc_thread = NULL;
kthread_stop(t);
}
if (ha->flags.fce_enabled)
qla2x00_disable_fce_trace(vha, NULL, NULL);
@ -2313,9 +2245,19 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
} else
ha->npiv_info = NULL;
/* Get consistent memory allocated for EX-INIT-CB. */
if (IS_QLA81XX(ha)) {
ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
&ha->ex_init_cb_dma);
if (!ha->ex_init_cb)
goto fail_ex_init_cb;
}
INIT_LIST_HEAD(&ha->vp_list);
return 1;
fail_ex_init_cb:
kfree(ha->npiv_info);
fail_npiv_info:
dma_free_coherent(&ha->pdev->dev, ((*rsp)->length + 1) *
sizeof(response_t), (*rsp)->ring, (*rsp)->dma);
@ -2398,18 +2340,22 @@ qla2x00_mem_free(struct qla_hw_data *ha)
if (ha->sfp_data)
dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);
if (ha->edc_data)
dma_pool_free(ha->s_dma_pool, ha->edc_data, ha->edc_data_dma);
if (ha->ms_iocb)
dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
if (ha->ex_init_cb)
dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
if (ha->s_dma_pool)
dma_pool_destroy(ha->s_dma_pool);
if (ha->gid_list)
dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
ha->gid_list_dma);
if (ha->init_cb)
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
ha->init_cb, ha->init_cb_dma);
@ -2428,6 +2374,8 @@ qla2x00_mem_free(struct qla_hw_data *ha)
ha->ms_iocb_dma = 0;
ha->init_cb = NULL;
ha->init_cb_dma = 0;
ha->ex_init_cb = NULL;
ha->ex_init_cb_dma = 0;
ha->s_dma_pool = NULL;
@ -2914,19 +2862,11 @@ qla2x00_timer(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&ha->hardware_lock,
cpu_flags);
}
set_bit(ABORT_QUEUES_NEEDED, &vha->dpc_flags);
start_dpc++;
}
/* if the loop has been down for 4 minutes, reinit adapter */
if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
DEBUG(printk("scsi(%ld): Loop down exceed 4 mins - "
"restarting queues.\n",
vha->host_no));
set_bit(RESTART_QUEUES_NEEDED, &vha->dpc_flags);
start_dpc++;
if (!(vha->device_flags & DFLG_NO_CABLE) &&
!vha->vp_idx) {
DEBUG(printk("scsi(%ld): Loop down - "
@ -3053,6 +2993,8 @@ qla2x00_release_firmware(void)
static pci_ers_result_t
qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
switch (state) {
case pci_channel_io_normal:
return PCI_ERS_RESULT_CAN_RECOVER;
@ -3060,7 +3002,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
pci_disable_device(pdev);
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
qla2x00_remove_one(pdev);
qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
return PCI_ERS_RESULT_DISCONNECT;
}
return PCI_ERS_RESULT_NEED_RESET;

View file

@ -612,8 +612,8 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
/* Good data. Use specified location. */
loc = locations[1];
*start = le16_to_cpu(fltl->start_hi) << 16 |
le16_to_cpu(fltl->start_lo);
*start = (le16_to_cpu(fltl->start_hi) << 16 |
le16_to_cpu(fltl->start_lo)) >> 2;
end:
DEBUG2(qla_printk(KERN_DEBUG, ha, "FLTL[%s] = 0x%x.\n", loc, *start));
return QLA_SUCCESS;
@ -629,6 +629,14 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
{ FA_BOOT_CODE_ADDR, FA_BOOT_CODE_ADDR, FA_BOOT_CODE_ADDR_81 };
const uint32_t def_vpd_nvram[] =
{ FA_VPD_NVRAM_ADDR, FA_VPD_NVRAM_ADDR, FA_VPD_NVRAM_ADDR_81 };
const uint32_t def_vpd0[] =
{ 0, 0, FA_VPD0_ADDR_81 };
const uint32_t def_vpd1[] =
{ 0, 0, FA_VPD1_ADDR_81 };
const uint32_t def_nvram0[] =
{ 0, 0, FA_NVRAM0_ADDR_81 };
const uint32_t def_nvram1[] =
{ 0, 0, FA_NVRAM1_ADDR_81 };
const uint32_t def_fdt[] =
{ FA_FLASH_DESCR_ADDR_24, FA_FLASH_DESCR_ADDR,
FA_FLASH_DESCR_ADDR_81 };
@ -693,6 +701,20 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
break;
case FLT_REG_VPD_0:
ha->flt_region_vpd_nvram = start;
if (!(PCI_FUNC(ha->pdev->devfn) & 1))
ha->flt_region_vpd = start;
break;
case FLT_REG_VPD_1:
if (PCI_FUNC(ha->pdev->devfn) & 1)
ha->flt_region_vpd = start;
break;
case FLT_REG_NVRAM_0:
if (!(PCI_FUNC(ha->pdev->devfn) & 1))
ha->flt_region_nvram = start;
break;
case FLT_REG_NVRAM_1:
if (PCI_FUNC(ha->pdev->devfn) & 1)
ha->flt_region_nvram = start;
break;
case FLT_REG_FDT:
ha->flt_region_fdt = start;
@ -722,13 +744,18 @@ no_flash_data:
ha->flt_region_fw = def_fw[def];
ha->flt_region_boot = def_boot[def];
ha->flt_region_vpd_nvram = def_vpd_nvram[def];
ha->flt_region_vpd = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
def_vpd0[def]: def_vpd1[def];
ha->flt_region_nvram = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
def_nvram0[def]: def_nvram1[def];
ha->flt_region_fdt = def_fdt[def];
ha->flt_region_npiv_conf = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
def_npiv_conf0[def]: def_npiv_conf1[def];
done:
DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
"vpd_nvram=0x%x fdt=0x%x flt=0x%x npiv=0x%x.\n", loc,
ha->flt_region_boot, ha->flt_region_fw, ha->flt_region_vpd_nvram,
"vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x "
"npiv=0x%x.\n", loc, ha->flt_region_boot, ha->flt_region_fw,
ha->flt_region_vpd_nvram, ha->flt_region_vpd, ha->flt_region_nvram,
ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_npiv_conf));
}
@ -931,31 +958,41 @@ done:
ha->npiv_info = NULL;
}
static void
qla24xx_unprotect_flash(struct qla_hw_data *ha)
static int
qla24xx_unprotect_flash(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
if (ha->flags.fac_supported)
return qla81xx_fac_do_write_enable(vha, 1);
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
if (!ha->fdt_wrt_disable)
return;
goto done;
/* Disable flash write-protection, first clear SR protection bit */
qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
/* Then write zero again to clear remaining SR bits.*/
qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
done:
return QLA_SUCCESS;
}
static void
qla24xx_protect_flash(struct qla_hw_data *ha)
static int
qla24xx_protect_flash(scsi_qla_host_t *vha)
{
uint32_t cnt;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
if (ha->flags.fac_supported)
return qla81xx_fac_do_write_enable(vha, 0);
if (!ha->fdt_wrt_disable)
goto skip_wrt_protect;
@ -973,6 +1010,26 @@ skip_wrt_protect:
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
return QLA_SUCCESS;
}
static int
qla24xx_erase_sector(scsi_qla_host_t *vha, uint32_t fdata)
{
struct qla_hw_data *ha = vha->hw;
uint32_t start, finish;
if (ha->flags.fac_supported) {
start = fdata >> 2;
finish = start + (ha->fdt_block_size >> 2) - 1;
return qla81xx_fac_erase_sector(vha, flash_data_addr(ha,
start), flash_data_addr(ha, finish));
}
return qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
(fdata & 0xff00) | ((fdata << 16) & 0xff0000) |
((fdata >> 16) & 0xff));
}
static int
@ -987,8 +1044,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
void *optrom = NULL;
struct qla_hw_data *ha = vha->hw;
ret = QLA_SUCCESS;
/* Prepare burst-capable write on supported ISPs. */
if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && !(faddr & 0xfff) &&
dwords > OPTROM_BURST_DWORDS) {
@ -1004,7 +1059,12 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
rest_addr = (ha->fdt_block_size >> 2) - 1;
sec_mask = ~rest_addr;
qla24xx_unprotect_flash(ha);
ret = qla24xx_unprotect_flash(vha);
if (ret != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Unable to unprotect flash for update.\n");
goto done;
}
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
fdata = (faddr & sec_mask) << 2;
@ -1017,9 +1077,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
ha->fdt_unprotect_sec_cmd,
(fdata & 0xff00) | ((fdata << 16) &
0xff0000) | ((fdata >> 16) & 0xff));
ret = qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
(fdata & 0xff00) |((fdata << 16) &
0xff0000) | ((fdata >> 16) & 0xff));
ret = qla24xx_erase_sector(vha, fdata);
if (ret != QLA_SUCCESS) {
DEBUG9(qla_printk("Unable to erase sector: "
"address=%x.\n", faddr));
@ -1073,8 +1131,11 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
0xff0000) | ((fdata >> 16) & 0xff));
}
qla24xx_protect_flash(ha);
ret = qla24xx_protect_flash(vha);
if (ret != QLA_SUCCESS)
qla_printk(KERN_WARNING, ha,
"Unable to protect flash after update.\n");
done:
if (optrom)
dma_free_coherent(&ha->pdev->dev,
OPTROM_BURST_SIZE, optrom, optrom_dma);
@ -1915,7 +1976,7 @@ qla2x00_resume_hba(struct scsi_qla_host *vha)
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_hba_online(vha);
qla2x00_wait_for_chip_reset(vha);
scsi_unblock_requests(vha->host);
}
@ -2206,11 +2267,7 @@ qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
rval = qla24xx_write_flash_data(vha, (uint32_t *)buf, offset >> 2,
length >> 2);
/* Resume HBA -- RISC reset needed. */
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
qla2x00_wait_for_hba_online(vha);
scsi_unblock_requests(vha->host);
return rval;
@ -2518,7 +2575,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
dcode = mbuf;
/* Begin with first PCI expansion ROM header. */
pcihdr = ha->flt_region_boot;
pcihdr = ha->flt_region_boot << 2;
last_image = 1;
do {
/* Verify PCI expansion ROM header. */

View file

@ -7,9 +7,9 @@
/*
* Driver version
*/
#define QLA2XXX_VERSION "8.03.00-k4"
#define QLA2XXX_VERSION "8.03.01-k1"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 3
#define QLA_DRIVER_PATCH_VER 0
#define QLA_DRIVER_PATCH_VER 1
#define QLA_DRIVER_BETA_VER 0

View file

@ -28,6 +28,7 @@
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/firmware.h>
#include <asm/byteorder.h>
@ -53,8 +54,6 @@
#define DEFAULT_LOOP_COUNT 10000
#include "qlogicpti_asm.c"
static struct qlogicpti *qptichain = NULL;
static DEFINE_SPINLOCK(qptichain_lock);
@ -465,16 +464,32 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
{
const struct firmware *fw;
const char fwname[] = "qlogic/isp1000.bin";
const __le16 *fw_data;
struct Scsi_Host *host = qpti->qhost;
unsigned short csum = 0;
unsigned short param[6];
unsigned short *risc_code, risc_code_addr, risc_code_length;
unsigned short risc_code_addr, risc_code_length;
int err;
unsigned long flags;
int i, timeout;
risc_code = &sbus_risc_code01[0];
err = request_firmware(&fw, fwname, &qpti->op->dev);
if (err) {
printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
fwname, err);
return err;
}
if (fw->size % 2) {
printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
fw->size, fwname);
err = -EINVAL;
goto outfirm;
}
fw_data = (const __le16 *)&fw->data[0];
risc_code_addr = 0x1000; /* all f/w modules load at 0x1000 */
risc_code_length = sbus_risc_code_length01;
risc_code_length = fw->size / 2;
spin_lock_irqsave(host->host_lock, flags);
@ -482,12 +497,12 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
* afterwards via the mailbox commands.
*/
for (i = 0; i < risc_code_length; i++)
csum += risc_code[i];
csum += __le16_to_cpu(fw_data[i]);
if (csum) {
spin_unlock_irqrestore(host->host_lock, flags);
printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!",
qpti->qpti_id);
return 1;
err = 1;
goto out;
}
sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL);
sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL);
@ -496,9 +511,9 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET))
udelay(20);
if (!timeout) {
spin_unlock_irqrestore(host->host_lock, flags);
printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id);
return 1;
err = 1;
goto out;
}
sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL);
@ -536,21 +551,21 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
if (qlogicpti_mbox_command(qpti, param, 1)) {
printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n",
qpti->qpti_id);
spin_unlock_irqrestore(host->host_lock, flags);
return 1;
err = 1;
goto out;
}
/* Load it up.. */
for (i = 0; i < risc_code_length; i++) {
param[0] = MBOX_WRITE_RAM_WORD;
param[1] = risc_code_addr + i;
param[2] = risc_code[i];
param[2] = __le16_to_cpu(fw_data[i]);
if (qlogicpti_mbox_command(qpti, param, 1) ||
param[0] != MBOX_COMMAND_COMPLETE) {
printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n",
qpti->qpti_id);
spin_unlock_irqrestore(host->host_lock, flags);
return 1;
err = 1;
goto out;
}
}
@ -569,8 +584,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
(param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n",
qpti->qpti_id);
spin_unlock_irqrestore(host->host_lock, flags);
return 1;
err = 1;
goto out;
}
/* Start using newly downloaded firmware. */
@ -583,8 +598,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
(param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: AboutFirmware cmd fails.\n",
qpti->qpti_id);
spin_unlock_irqrestore(host->host_lock, flags);
return 1;
err = 1;
goto out;
}
/* Snag the major and minor revisions from the result. */
@ -599,8 +614,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
(param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: could not set clock rate.\n",
qpti->qpti_id);
spin_unlock_irqrestore(host->host_lock, flags);
return 1;
err = 1;
goto out;
}
if (qpti->is_pti != 0) {
@ -616,8 +631,11 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
qlogicpti_mbox_command(qpti, param, 1);
}
out:
spin_unlock_irqrestore(host->host_lock, flags);
return 0;
outfirm:
release_firmware(fw);
return err;
}
static int qlogicpti_verify_tmon(struct qlogicpti *qpti)
@ -1458,6 +1476,7 @@ MODULE_DESCRIPTION("QlogicISP SBUS driver");
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_LICENSE("GPL");
MODULE_VERSION("2.1");
MODULE_FIRMWARE("qlogic/isp1000.bin");
module_init(qpti_init);
module_exit(qpti_exit);

File diff suppressed because it is too large Load diff

View file

@ -169,12 +169,10 @@ scsi_pool_alloc_command(struct scsi_host_cmd_pool *pool, gfp_t gfp_mask)
{
struct scsi_cmnd *cmd;
cmd = kmem_cache_alloc(pool->cmd_slab, gfp_mask | pool->gfp_mask);
cmd = kmem_cache_zalloc(pool->cmd_slab, gfp_mask | pool->gfp_mask);
if (!cmd)
return NULL;
memset(cmd, 0, sizeof(*cmd));
cmd->sense_buffer = kmem_cache_alloc(pool->sense_slab,
gfp_mask | pool->gfp_mask);
if (!cmd->sense_buffer) {

View file

@ -791,7 +791,22 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
"%d bytes done.\n",
req->nr_sectors, good_bytes));
/* A number of bytes were successfully read. If there
/*
* Recovered errors need reporting, but they're always treated
* as success, so fiddle the result code here. For BLOCK_PC
* we already took a copy of the original into rq->errors which
* is what gets returned to the user
*/
if (sense_valid && sshdr.sense_key == RECOVERED_ERROR) {
if (!(req->cmd_flags & REQ_QUIET))
scsi_print_sense("", cmd);
result = 0;
/* BLOCK_PC may have set error */
error = 0;
}
/*
* A number of bytes were successfully read. If there
* are leftovers and there is some kind of error
* (result != 0), retry the rest.
*/

View file

@ -1051,12 +1051,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
good_bytes = sd_completed_bytes(SCpnt);
break;
case RECOVERED_ERROR:
/* Inform the user, but make sure that it's not treated
* as a hard error.
*/
scsi_print_sense("sd", SCpnt);
SCpnt->result = 0;
memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
good_bytes = scsi_bufflen(SCpnt);
break;
case NO_SENSE:

View file

@ -264,6 +264,7 @@ struct ses_host_edev {
struct enclosure_device *edev;
};
#if 0
int ses_match_host(struct enclosure_device *edev, void *data)
{
struct ses_host_edev *sed = data;
@ -280,6 +281,7 @@ int ses_match_host(struct enclosure_device *edev, void *data)
sed->edev = edev;
return 1;
}
#endif /* 0 */
static void ses_process_descriptor(struct enclosure_component *ecomp,
unsigned char *desc)

View file

@ -1312,8 +1312,10 @@ static void sg_rq_end_io(struct request *rq, int uptodate)
wake_up_interruptible(&sfp->read_wait);
kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN);
kref_put(&sfp->f_ref, sg_remove_sfp);
} else
execute_in_process_context(sg_rq_end_io_usercontext, &srp->ew);
} else {
INIT_WORK(&srp->ew.work, sg_rq_end_io_usercontext);
schedule_work(&srp->ew.work);
}
}
static struct file_operations sg_fops = {
@ -1656,10 +1658,30 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
md->null_mapped = hp->dxferp ? 0 : 1;
}
if (iov_count)
res = blk_rq_map_user_iov(q, rq, md, hp->dxferp, iov_count,
hp->dxfer_len, GFP_ATOMIC);
else
if (iov_count) {
int len, size = sizeof(struct sg_iovec) * iov_count;
struct iovec *iov;
iov = kmalloc(size, GFP_ATOMIC);
if (!iov)
return -ENOMEM;
if (copy_from_user(iov, hp->dxferp, size)) {
kfree(iov);
return -EFAULT;
}
len = iov_length(iov, iov_count);
if (hp->dxfer_len < len) {
iov_count = iov_shorten(iov, iov_count, hp->dxfer_len);
len = hp->dxfer_len;
}
res = blk_rq_map_user_iov(q, rq, md, (struct sg_iovec *)iov,
iov_count,
len, GFP_ATOMIC);
kfree(iov);
} else
res = blk_rq_map_user(q, rq, md, hp->dxferp,
hp->dxfer_len, GFP_ATOMIC);
@ -2079,7 +2101,8 @@ static void sg_remove_sfp(struct kref *kref)
write_unlock_irqrestore(&sg_index_lock, iflags);
wake_up_interruptible(&sdp->o_excl_wait);
execute_in_process_context(sg_remove_sfp_usercontext, &sfp->ew);
INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext);
schedule_work(&sfp->ew.work);
}
static int

View file

@ -309,15 +309,6 @@ static int sr_done(struct scsi_cmnd *SCpnt)
break;
case RECOVERED_ERROR:
/*
* An error occured, but it recovered. Inform the
* user, but make sure that it's not treated as a
* hard error.
*/
scsi_print_sense("sr", SCpnt);
SCpnt->result = 0;
SCpnt->sense_buffer[0] = 0x0;
good_bytes = this_count;
break;

File diff suppressed because it is too large Load diff

View file

@ -234,7 +234,7 @@ static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host)
/*
* Set the status field of a CAM CCB.
*/
static __inline void
static inline void
sym_set_cam_status(struct scsi_cmnd *cmd, int status)
{
cmd->result &= ~(0xff << 16);
@ -244,7 +244,7 @@ sym_set_cam_status(struct scsi_cmnd *cmd, int status)
/*
* Get the status field of a CAM CCB.
*/
static __inline int
static inline int
sym_get_cam_status(struct scsi_cmnd *cmd)
{
return host_byte(cmd->result);
@ -253,7 +253,7 @@ sym_get_cam_status(struct scsi_cmnd *cmd)
/*
* Build CAM result for a successful IO and for a failed IO.
*/
static __inline void sym_set_cam_result_ok(struct sym_ccb *cp, struct scsi_cmnd *cmd, int resid)
static inline void sym_set_cam_result_ok(struct sym_ccb *cp, struct scsi_cmnd *cmd, int resid)
{
scsi_set_resid(cmd, resid);
cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));

View file

@ -602,7 +602,7 @@ sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fa
/*
* Set initial io register bits from burst code.
*/
static __inline void sym_init_burst(struct sym_hcb *np, u_char bc)
static inline void sym_init_burst(struct sym_hcb *np, u_char bc)
{
np->rv_ctest4 &= ~0x80;
np->rv_dmode &= ~(0x3 << 6);

View file

@ -1096,7 +1096,7 @@ do { \
#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
static inline void
sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
{
u32 h = (badd>>32);
@ -1201,7 +1201,7 @@ dma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);
#define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2)
static __inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
static inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{
void *vaddr = NULL;
dma_addr_t baddr = 0;
@ -1215,7 +1215,7 @@ static __inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
return vaddr;
}
static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
static inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{
dma_free_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, vbp->vaddr,
vbp->baddr);

View file

@ -262,7 +262,7 @@ static void ___free_dma_mem_cluster(m_pool_p mp, void *m)
#endif
/* Fetch the memory pool for a given pool id (i.e. DMA constraints) */
static __inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
static inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
{
m_pool_p mp;
for (mp = mp0.next;

View file

@ -52,17 +52,17 @@ typedef struct sym_quehead {
(ptr)->flink = (ptr); (ptr)->blink = (ptr); \
} while (0)
static __inline struct sym_quehead *sym_que_first(struct sym_quehead *head)
static inline struct sym_quehead *sym_que_first(struct sym_quehead *head)
{
return (head->flink == head) ? 0 : head->flink;
}
static __inline struct sym_quehead *sym_que_last(struct sym_quehead *head)
static inline struct sym_quehead *sym_que_last(struct sym_quehead *head)
{
return (head->blink == head) ? 0 : head->blink;
}
static __inline void __sym_que_add(struct sym_quehead * new,
static inline void __sym_que_add(struct sym_quehead * new,
struct sym_quehead * blink,
struct sym_quehead * flink)
{
@ -72,19 +72,19 @@ static __inline void __sym_que_add(struct sym_quehead * new,
blink->flink = new;
}
static __inline void __sym_que_del(struct sym_quehead * blink,
static inline void __sym_que_del(struct sym_quehead * blink,
struct sym_quehead * flink)
{
flink->blink = blink;
blink->flink = flink;
}
static __inline int sym_que_empty(struct sym_quehead *head)
static inline int sym_que_empty(struct sym_quehead *head)
{
return head->flink == head;
}
static __inline void sym_que_splice(struct sym_quehead *list,
static inline void sym_que_splice(struct sym_quehead *list,
struct sym_quehead *head)
{
struct sym_quehead *first = list->flink;
@ -101,7 +101,7 @@ static __inline void sym_que_splice(struct sym_quehead *list,
}
}
static __inline void sym_que_move(struct sym_quehead *orig,
static inline void sym_que_move(struct sym_quehead *orig,
struct sym_quehead *dest)
{
struct sym_quehead *first, *last;
@ -129,7 +129,7 @@ static __inline void sym_que_move(struct sym_quehead *orig,
#define sym_insque_head(new, head) __sym_que_add(new, head, (head)->flink)
static __inline struct sym_quehead *sym_remque_head(struct sym_quehead *head)
static inline struct sym_quehead *sym_remque_head(struct sym_quehead *head)
{
struct sym_quehead *elem = head->flink;
@ -142,7 +142,7 @@ static __inline struct sym_quehead *sym_remque_head(struct sym_quehead *head)
#define sym_insque_tail(new, head) __sym_que_add(new, (head)->blink, head)
static __inline struct sym_quehead *sym_remque_tail(struct sym_quehead *head)
static inline struct sym_quehead *sym_remque_tail(struct sym_quehead *head)
{
struct sym_quehead *elem = head->blink;

View file

@ -41,6 +41,11 @@ fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin
fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \
e100/d102e_ucode.bin
fw-shipped-$(CONFIG_PCMCIA_SMC91C92) += ositech/Xilinx7OD.bin
fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \
advansys/3550.bin advansys/38C0800.bin
fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \
qlogic/12160.bin
fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin
fw-shipped-$(CONFIG_SMCTR) += tr_smctr.bin
fw-shipped-$(CONFIG_SND_KORG1212) += korg/k1212.dsp
fw-shipped-$(CONFIG_SND_MAESTRO3) += ess/maestro3_assp_kernel.fw \

View file

@ -45,6 +45,32 @@ Found alsa-firmware package in hex form, with the following comment:
--------------------------------------------------------------------------
Driver: SCSI_ADVANSYS - AdvanSys SCSI
File: advansys/mcode.bin
File: advansys/3550.bin
File: advansys/38C0800.bin
File: advansys/38C1600.bin
Licence: BSD, no source available.
Found in hex form in kernel source.
--------------------------------------------------------------------------
Driver: SCSI_QLOGIC_1280 - Qlogic QLA 1240/1x80/1x160 SCSI support
File: qlogic/1040.bin
File: qlogic/1280.bin
File: qlogic/12160.bin
Licence: Allegedly GPLv2+, but no source visible. Marked:
QLOGIC LINUX SOFTWARE
QLogic ISP1280/ device driver for Linux 2.2.x and 2.4.x
Copyright (C) 2001 Qlogic Corporation (www.qlogic.com)
--------------------------------------------------------------------------
Driver: smctr -- SMC ISA/MCA Token Ring adapter
File: tr_smctr.bin
@ -596,3 +622,13 @@ Licence: Allegedly GPL, but no source visible. Marked:
Found in hex form in kernel source.
--------------------------------------------------------------------------
Driver: SCSI_QLOGICPTI - PTI Qlogic, ISP Driver
File: qlogic/isp1000.bin
Licence: Unknown
Found in hex form in kernel source.
--------------------------------------------------------------------------

View file

@ -0,0 +1,317 @@
:10000000DD2DD504000000F200F0001618E400FC1D
:10001000010048E4BE18188003F6020000FAFFFF52
:10002000280E9EE7FF0082E700EA00F601E609E7F6
:1000300055F001F601FA08000300040018F410005E
:1000400000EC85F0BC00D5F08E0C385400E61EF0B4
:1000500086F0B4009857D0010C1C3E1C0C00BB006D
:10006000AA18028032F001FC880CC6120213184054
:10007000005701EA3C006C016E0104123E570080FB
:1000800003E6B600C00001013E01DA0F221008129B
:10009000024AB95403581B8030E44BE4200032007C
:1000A0003E00800024013C0168016A017001720178
:1000B000740176017801620A920C2C102E1006133E
:1000C0004C1CBB553C5604804AE402EE5BF0B1F098
:1000D00003F706F703FC0F004000BE000001B00864
:1000E00030136415321C381C4E1C10440248004C5E
:1000F00004EA5DF004F602FC0500340036009800C6
:10010000CC0020014E014E0B1E0E0C100A120413DF
:100110004013301C004EBD56068300DC05F009F08C
:1001200059F0A7F0B8F00EF70600190033009B0055
:10013000A400B500BA00D000E100E700DE03560AD3
:10014000140E021004100A1036100A131213521360
:1001500010151415AC16201C341C361C08443844E9
:1001600091440A454846014868548355B0570158A0
:10017000835905E60BF00CF05CF04BF404F805F83D
:1001800002FA03FA04FC05FC07000A000D001C003B
:100190009E00A800AA00B900E00022012601790112
:1001A0007A01C001C2017C025A03EA04E807680828
:1001B0006908BA08E909060B3A0E00101A10ED108A
:1001C000F11006120C1316131E1382134214D614C8
:1001D0008A15C617D2176B18121C461C9C32004099
:1001E0000E47484741488948804C00544455E555DE
:1001F00014567757BF57405C0680089003A1FE9CB9
:10020000F02902FEB80CFF100000D0FECC1800CF81
:10021000FE8001FF030000FE9315FE0F05FF38006E
:1002200000FE572400FE48004FFF04000010FF09A5
:100230000000FF080101FF08FFFFFF270000FF107B
:10024000FFFFFF0F0000FE7856FE3412FF21000072
:10025000FE04F7CF2A670B01FECE0EFE04F7CF6730
:100260000B3C2AFE3DF0FE0202FE20F09CFE91F0C7
:10027000FEF001FE90F0FEF001FE8FF09C05513B78
:1002800002FED40C01FE440DFEDD12FEFC10FE2821
:100290001C05FEA600FED3124718FEA600B5FE48B8
:1002A000F0FE8602FE49F0FEA002FE4AF0FEBE020B
:1002B000FE46F0FE5002FE47F0FE5602FE43F0FE00
:1002C0004402FE44F0FE4802FE45F0FE4C02170BCD
:1002D000A0170618960229FE001CDEFE021CDDFE99
:1002E0001E1CFEE91001FE2017FEE710FE06FCC7EB
:1002F0000A6B019E0229144D379701FE640F0A6BA9
:100300000182FEBD100A6B0182FEAD10FE161CFEBE
:10031000581C170618962A2529FE3DF0FE020221D8
:10032000FE9402FE5A1CEAFE141C14FE300037979D
:1003300001FE540F1706189602D01E20071034FE37
:10034000691017061896FE04EC20463D1220FE05A3
:10035000F6C701FE5216094A4C35112D3C8A01E6BA
:1003600002290A40010E07005D016FFE1810FE41D0
:10037000580A99010EFEC85464FE0C0301E60229D6
:100380002A46FE02E827F8FE9E43F7FE27F0FEDC31
:1003900001FE074BFE20F09CFE401C25D2FE26F0FD
:1003A000FE5603FEA0F0FE4403FE11F09CFEEF108B
:1003B000FE9FF0FE6403EB0FFE1100025A2AFE4876
:1003C0001CEB09041DFE1813231E98AC12980A405A
:1003D000010EAC7501FEBC1511CA25D2FE01F0D28A
:1003E000FE82F0FE9203EC11FEE40065FEA40325FC
:1003F000321FFEB4030143FE06F0FEC4038D81FEEE
:100400000AF0FE7A060222056B2816FEF604142C6A
:1004100001338FFE660202D1EB2A671AFE671BF8D2
:10042000F7FE481C70016E870A40010E070016D3C4
:100430000ACA010E7460597627056B28FE10121443
:100440002C01338FFE660202D1BC7DBD7F25226563
:10045000FE3C041FFE380468FEA000FE9B57FE4EC3
:10046000122BFF02001001081FFEE0042B01081FE1
:1004700022302ED5FE4C44FE4C1260FE4448132C14
:10048000FE4C5464D3467627FAEFFE621309041D2E
:10049000FE2A132F077EA5FE2010132CFE4C546459
:1004A000D3FAEF8609041DFE08132F077E6E090498
:1004B0001DFE1C1214920904063B14C401338FFE66
:1004C000700C02222B11FEE600FE1C90F903149220
:1004D00001330229FE425B671AFE4659F8F7FE8790
:1004E00080FE31E44F09040BFE7813FE2080071ACA
:1004F000FE7012490406FE601305FEA2002816FED7
:100500008005FE31E46A49040BFE4A1305FEA00093
:1005100028FE42125E01082532F1010826FE9805E8
:1005200011FEE3002349FE4AF0FE6A05FE49F0FE93
:1005300064058324FE2100A124FE2200A0244CFE99
:100540000948010826FE9805FEE2084904C53B015A
:1005500086240612CC37FE270109041DFE2212470D
:1005600001A714920904063B14C401338FFE700CDA
:10057000022205FE9C0028FE3E12055028FE36137E
:100580004701A726FE08060A06490419FE02125F63
:1005900001FEAA141FFEFE05119A014311FEE5009B
:1005A0000550B40C5005C628FE6212053F28FE5ABD
:1005B0001301FE141801FE6618FE4348B719136CA8
:1005C000FF020057488B1C3D85B7694701A726FEEF
:1005D000720649041BDF890A4D01FED8141FFE680C
:1005E00006119A014311FEE500053FB40C3F1706C2
:1005F00001A7EC7270016E8711FEE200010825323E
:10060000FE0AF0FEA6068CFE5C07FE06F0FE6407FE
:100610008D81022209040BFE2E12151A0108150005
:1006200001081500010815000108FE99A40108152C
:100630000002FE320861041BFE381209041B6E150D
:10064000FE1B000108150001081500010815000136
:100650000815060108150002D9664CFE3A555FFEE2
:100660009A814B1DBAFE32070A1DFE096FAFFECA02
:1006700045FE3212622C85667B01082532FE0AF0A7
:10068000FE32078D818CFE5C070222014302FE8A46
:1006900006151902FE8A06FE9CF7D4FE2C90FEAECB
:1006A0009077FECA070C541855094A6A351E200770
:1006B00010FE0E1274FE808037206327FE0610FEA7
:1006C00083E7C4A1FE0340094A4F3501A8ADFE1FD0
:1006D00040125801A5FE0850FE8A50FE4451FEC645
:1006E0005183FBFE8A900C521853FE0C90FE8E90A4
:1006F000FE4050FEC2500C39183AFE4A1009046AF6
:10070000FE2A12FE2C90FEAE900C54185509044F90
:100710008501A8FE1F801258FE4490FEC6900C561C
:100720001857FBFE8A900C521853FE4090FEC29060
:100730000C39183A0C38184E094A19352A13FE4E4E
:100740001165FE4808FE9EF0FE5C08B116322A7361
:10075000DDB8FE8008B9FE9E088CFE7408FE06F027
:10076000FE7A088D8102220143FEC9101519FEC9C7
:1007700010610406FE101261040B4509040BFE68AB
:1007800012FE2E1C02FE240A6104064561040BFEC3
:100790005212FE2C1CFEAAF0FE1E09FEACF0FEBE9C
:1007A00008FE8A10AAFEF310FEADF0FECA0802FE93
:1007B000240AABFEE710FE2BF09DE91CFE00FEFEB6
:1007C0001C12B5FED2F09DFE76181C1A169D05CBA4
:1007D0001C06169DB86DB96DAAABFEB110705E2BEC
:1007E000149201330FFE3500FE01F05A0F7C025ABD
:1007F000FE74181CFE00F8166D671B01FE440D3BCD
:1008000001E61E2774671A026D09040B21FE060A11
:1008100009046AFE8212090419FE66131E58ACFC14
:10082000FE8380FEC844FE2E13FE0491FE86916373
:1008300027FE4059FEC15977D7055431550C7B1816
:100840007CBE54BF5501A8AD63271258C038C14EB5
:1008500079566857F4F5FE04FA38FE05FA4E01A5FC
:10086000A2230C7B0C7C79566857FE1210090419E0
:1008700016D77939683A0904FEF700350552315325
:10088000FE1058FE9158FE1459FE9559026D090448
:100890001916D70904FEF70035FE3A55FE19815F97
:1008A000FE1090FE9290FED7102F079B16FEC608F2
:1008B000119B09040BFE14130539313A77FEC60863
:1008C000FE0C58FE8D58026D2347FE1980DE090488
:1008D0000BFE1A12FE6C19FE1941E9B5FED1F0D9D2
:1008E000147A01330FFE4400FE8E10FE6C19BE39DF
:1008F000FEED19BF3AFE0C51FE8E51E91CFE00FFC1
:1009000034FE7410B5FED2F0FEB20AFE76181C1A40
:100910008405CB1C06FE08130FFE1600025AFED1FA
:10092000F0FEC40A147A01330FFE1700FE4210FED7
:10093000CEF0FECA0AFE3C10FECDF0FED60A0FFE37
:100940002200025AFECBF0FEE20A0FFE2400025AF9
:10095000FED0F0FEEC0A0F93DCFECFF0FEF60A0F9D
:100960004CFE1010FECCF0D96104193B0FFE1200B2
:100970002A13FE4E1165FE0C0BFE9EF0FE200BB1FD
:1009800016322A73DDB822B9222AEC65FE2C0B251B
:10099000328CFE480B8D81B8D4B9D402220143FEBB
:1009A000DB1011FEE800AAAB70BC7DBD7FFE89F0B4
:1009B00022302ED8BC7DBD7F01081F22302ED6B13B
:1009C000450FFE4200025A7806FE814916FE380C99
:1009D00009040BFE44130F004B0BFE54124BFE2870
:1009E0000021FEA60C0A40010E07005D3EFE280015
:1009F000FEE21001E701E80A9901FE320E59112DBD
:100A0000016F02290FFE44004B0BDF3E0BFEB410BA
:100A100001863E0BFEAA100186FE1982FE3446A313
:100A20003E0B0FFE4300FE9610094A0B3501E7010D
:100A3000E859112D016F670B593C8A02FE2A030900
:100A4000040B843E0B0F00FE5C1061041BFE581269
:100A500009041BFE5013FE1C1CFE9DF0FE5C0CFEE8
:100A60001C1CFE9DF0FE620C094A1B35FEA9100FEE
:100A7000FE1500FE04E60B5F5C0FFE1300FE101077
:100A80000FFE4700A10FFE4100A00FFE240087AA21
:100A9000AB70056B2821D15FFE04E61BFE9D41FE75
:100AA0001C425901DA0229EA140B3795A914FE31C8
:100AB00000379701FE540F02D03CFE06ECC9EE3E13
:100AC0001DFECE45343CFE06EAC9FE474B89FE7545
:100AD000570551FE9856FE38120A42010EFE444850
:100AE0004609041DFE1A130A40010E47FE41580A2A
:100AF00099010EFE49548EFE2A0D02FE2A030A5168
:100B0000FEEE14EE3E1DFECE45343CFECE47FEAD5D
:100B10001302291E200710FE9E1223124D1294125A
:100B2000CE1E2D47372DB1E0FEBCF0FEEC0D1306B6
:100B3000124D01FEE21505FE380131FE3A0177FE45
:100B4000F00DFE02ECCE62005DFE04EC2046FE05D8
:100B5000F6FE340101FE5216FBFE48F40DFE18139A
:100B6000AFFE02EACE627AFEC513141B3795A95C6C
:100B700005FE38011CFEF0FF0CFE600105FE3A0187
:100B80000CFE62013D12202406122D112D8A13063F
:100B90000323031E4DFEF7121E94AC1294077AFE37
:100BA0007113FE241C141A3795A9FED910B6FE0342
:100BB000DCFE7357FE805D03B6FE03DCFE5B57FE72
:100BC000805D03FE0357B623FE00CC03FE0357B639
:100BD000750309044CFE2213FE1C800706FE1A133F
:100BE000FE1E80E1FE1D80A4FE0C90FE0E13FE0E84
:100BF00090A3FE3C90FE30F40BFE3C50A001FE8220
:100C0000162F072DE001FEBC1509041D4501E70163
:100C1000E811FEE90009044CFE2C1301FE1416FE37
:100C20001E1CFE1490FE96900CFE640118FE6601D8
:100C300009044FFE1212FE038074FE01EC20FE80B8
:100C4000401220632711C8591E20ED762003FE08AC
:100C50001C05FEAC00FE065805FEAE00FE0758055A
:100C6000FEB000FE085805FEB200FE0958FE0A1C40
:100C7000246912C9230C500C3F1340485F171DFE16
:100C8000904DFE915421FE080F3E10134248174C20
:100C9000FE904DFE915421FE1E0F24101220782C40
:100CA000461E20ED762011C8F6FED6F0FE320FEA81
:100CB00070FE141CFE101CFE181C033CFE0C14EEEF
:100CC000FE07E61DFECE47FEF513030186782C468F
:100CD000FAEFFE42132F072DFE34130A42010EB025
:100CE000FE3612F0FE454801E3FE00CCB0FEF313E1
:100CF0003D750710A30A80010EFE805C016FFE0E99
:100D000010077E45F6FED6F0FE6C0F03FE445874C5
:100D1000FE01EC97FE9E40FE9DE700FE9CE71B76E1
:100D20002701DAFEDD102ABC7DBD7F302ED5071BE2
:100D3000FE4812070BFE5612071AFE301207C216A3
:100D4000FE3E1107FE230016FE4A11070616FEA8F6
:100D5000110719FE12120700162214C201339F2B2D
:100D600001088C43032BFE62080ACA01FE320E11F1
:100D70007E02292B2F079BFED9137939683A77FE1B
:100D8000FC1009046AFE7212C038C14EF4F58EFEE2
:100D9000C6101E58FE2613057B317C77FE820C0C94
:100DA000541855230C7B0C7C01A82469731258013C
:100DB000A5C038C14EFE0455FEA555FE04FA38FE06
:100DC00005FA4EFE911005563157FE4056FEE1568B
:100DD0000C56185783C038C14EF4F505523153FEF6
:100DE0000056FEA1560C52185309046AFE1E121E2C
:100DF00058FE1F4005543155FE2C50FEAE5005568E
:100E00003157FE4450FEC65005523153FE0850FE85
:100E10008A500539313AFE4050FEC250025C240629
:100E200012CD025B2B01081F44302ED5070621444A
:100E30002F079B215B016E1C3D164409040BE279D0
:100E400039683AFE0A5534FE8B55BE39BF3AFE0C5E
:100E500051FE8E51025BFE1981AFFE1941025B2BE0
:100E6000010825321FA2302ED84B1AFEA6124B0BBA
:100E70003B0244010825321FA2302ED6071A214416
:100E800001081FA2302EFEE809FEC2496005FE9C43
:100E9000002884490419349FFEBB454B00453E069B
:100EA000783DFEDA14016E87FE4B45E22F079AE18A
:100EB00005C62884053F28345E025BFEC05DFEF84F
:100EC00014FE03170550B40C505E2B0108265C017C
:100ED000FEAA14025C010825321F44302ED60706F4
:100EE000214401FE8E13FE4258FE8214FEA4148794
:100EF000FE4AF40B1644FE4AF406FE0C122F079A23
:100F000085025B053FB40C3F5E2B0108265C01FEA9
:100F1000D814025C130665FECA1226FEE01272F1B6
:100F200001082372038FFEDC1225FEDC121FFECAAD
:100F3000125E2B0108FED510136CFF020057488B80
:100F40001CFEFF7FFE3056FE005C03136CFF0200A8
:100F500057488B1C3DFE3056FE005C03136CFF02AD
:100F60000057488B03136CFF020057488BFE0B5849
:100F7000030A5001820A3F018203FC1C10FF030098
:100F800054FE00F41948FE007DFE017DFE027DFE48
:100F9000037C63270C521853BE56BF5703FE6208EA
:100FA000FE824AFEE11AFE835A740301FE1418FE03
:100FB00042485F608901081FFEA214302ED8010844
:100FC0001FFEA214302EFEE80AFEC15905C628FEF7
:100FD000CC1249041BFEC41323621BE24BC364FE04
:100FE000E8133B130617C378DBFE7810FF02835526
:100FF000A1FF028355621AA4BBFE30008EE4172CB9
:101000001306FE5610620BE1BBFE64008EE40AFE7E
:10101000640017931306FE28106206FE6013BBFEE1
:10102000C8008EE40AFEC800174D130683BBFE906D
:1010300001BAFE4E1489FE1210FE43F494FE56F0DF
:10104000FE6014FE04F46CFE43F493FEF310F90109
:10105000FE22131C3DFE1013FE0017FE4DE469BA7C
:10106000FE9C14B769FE1C10FE0017FE4DE419BA71
:10107000FE9C14B719836023FE4DF400DF8913062C
:10108000FEB456FEC3580360130B03150601082671
:10109000E5150B010826E5151A010826E572FE89FB
:1010A000490108031506010826A6151A010826A6F7
:1010B0001506010826A6FE8949010826A672FE89A2
:1010C0004A01080360031ECC0706FE4413AD12CC90
:1010D000FE49F4003B729F5EFE01ECFE2701F10128
:1010E000082F07FEE300FE20131FFE5A152312CD22
:1010F00001431ECD070645094A0635030A42010E83
:10110000ED880710A40A80010E880A51019E030A87
:1011100080010E88FE80E710071084FE455801E329
:1011200088030A42010E880A51019E030A42010EF9
:10113000FE8080F2FE49E410A40A80010EF20A51FA
:1011400001820317107166FE6001FE18DFFE19DED2
:10115000FE241CFE1DF71D90FEF61501FEFC16E098
:10116000911D66FE2C01FE2F1903AE21FEE615FE31
:10117000DA1017107105FE6401FE00F419FE18580C
:1011800005FE6601FE19589119FE3C90FE30F406EA
:10119000FE3C5066FE3800FE0F79FE1CF71990FEEB
:1011A0004016FEB6143403AE21FE1816FE9C10172E
:1011B0001071FE835AFE18DFFE19DEFE1DF738900F
:1011C000FE6216FE9414FE10139138661BFEAF19D2
:1011D000FE98E70003AE21FE5616FE6C1017107144
:1011E000FE30BCFEB2BC91C5661BFE0F79FE1CF73B
:1011F000C590FE9A16FE5C143403AE21FE8616FEE0
:101200004210FE02F61071FE18FE54FE19FE55FC47
:10121000FE1DF74F90FEC016FE3614FE1C13914FB4
:1012200047FE8358FEAF19FE80E710FE81E71011DC
:10123000FEDD006327036327FE124521FEB016146E
:10124000063795A90229FE39F0FE04172303FE7E16
:10125000181C1A5D130D037105CB1C06FEEF12FE60
:10126000E110782C462F072DFE3C13FE8214FE421F
:10127000133C8A0A42010EB0FE3E12F0FE454801C0
:10128000E3FE00CCB0FEF3133D750710A30A800106
:101290000EF2016FFE1610077E85FE4014FE24122A
:1012A000F6FED6F0FE2417170B03FE9CE70B0FFE8D
:1012B000150059762701DA1706033C8A094A1D35BD
:1012C000112D016F170603FE3890FEBA9079C7689A
:1012D000C8FE485534FEC955031E98731298030A78
:1012E00099010EF00A40010EFE494416FEF01773F4
:1012F00075030A42010E0710450A51019E0A40017A
:101300000E737503FE4EE41A64FE241805FE900069
:10131000FE3A455BFE4EE4C264FE361805FE9200BE
:10132000FE02E61BDCFE4EE4FE0B0064FE481805E0
:10133000FE9400FE02E619FE081005FE9600FE026D
:10134000E62CFE4E45FE0C12AFFF046854DE1C690D
:1013500003077AFE5AF0FE741824FE0900FE3410CA
:10136000071BFE5AF0FE821824C3FE2610071A5DE2
:10137000242CDC070B5D2493FE0E1007065D244D24
:101380009FAD0314FE09000133FE04FE7D057FF9C5
:101390000325FECA18FE14F00865FEC61803FF1ADE
:0213A00000004B
:00000001FF
/* Microcode buffer is kept after initialization for error recovery. */

View file

@ -0,0 +1,336 @@
:10000000D83F0D05000000F200F000FC001618E4D7
:10001000010048E4188003F60200CE1900FAFFFF41
:100020001C0F00F69EE7FF0082E700EA01FA01E6F6
:1000300009E755F001F60300040010001EF085F0FA
:1000400018F40800BC00385400ECD5F0820D00E62E
:1000500086F0B1F0985701FCB400D4010C1C3E1C92
:100060003C00BB000010BA19028032F07C0D021374
:10007000BA131840005701EA02FC03FC3E006C0171
:100080006E0174017601B9543E57008003E6B60054
:10009000C00001013E017A01CA08CE1016110412F7
:1000A0000812024ABB553C5603581B8030E44BE40F
:1000B0005DF002FA200032004000800024013C0183
:1000C00068016A017001720178017C01620A860D83
:1000D00006134C1C04804AE402EE5BF003F70C00AC
:1000E0000F004700BE00000120115C16321C381CB6
:1000F0004E1C1044004C04EA5CF0A7F004F603FA2E
:100100000500340036009800CC0020014E014A0B57
:10011000420C120F0C1022110A120413301C024858
:10012000004E42544455BD56068300DC05F009F0EC
:1001300059F0B8F04BF406F70EF704FC05FC060086
:10014000190033009B00A400B500BA00D000E10004
:10015000E700E203080F021004100A100A130C1340
:1001600012132414341404160816A417201C341C6B
:10017000361C0844384491440A45484601486854AE
:100180003A558355E555B0570158835905E60BF0AC
:100190000CF004F805F807000A001C001E009E0081
:1001A000A800AA00B900E0002201260179017E0121
:1001B000C401C60180025E03EE049A06F8076208D5
:1001C00068086908D608E909FA0B2E0F12101A10F0
:1001D000ED10F1102A1106120C123E121013161314
:1001E0001E134614761482143615CA156B18BE18E1
:1001F000CA18E619121C461C9C3200400E47FE9C91
:10020000F02B02FEAC0DFF100000D7FEE81900D65F
:10021000FE8401FF030000FE9315FE0F05FF38006A
:1002200000FE572400FE4C005BFF04000011FF0994
:100230000000FF080101FF08FFFFFF270000FF107B
:10024000FFFFFF110000FE7856FE3412FF21000070
:10025000FE04F7D62C990A01FEC20FFE04F7D699C8
:100260000A422CFE3DF0FE0602FE20F0A7FE91F0B1
:10027000FEF401FE90F0FEF401FE8FF0A7035D4D49
:1002800002FEC80D01FE380EFEDD12FEFC10FE2837
:100290001C03FEA600FED3124114FEA600C2FE48B7
:1002A000F0FE8A02FE49F0FEA402FE4AF0FEC202FF
:1002B000FE46F0FE5402FE47F0FE5A02FE43F0FEF8
:1002C0004802FE44F0FE4C02FE45F0FE5002180AC1
:1002D000AA180614A1022BFE001CE7FE021CE6FE73
:1002E0001E1CFEE91001FE1818FEE710FE06FCCEEB
:1002F000097001A8022B155939A201FE5810097086
:100300000187FEBD1009700187FEAD10FE161CFEB0
:10031000581C180614A12C1C2BFE3DF0FE060223CF
:10032000FE9802FE5A1CF8FE141C15FE300039A27D
:1003300001FE4810180614A102D72220071135FE2D
:100340006910180614A1FE04EC204F431320FE058B
:10035000F6CE01FE4A1708545837122F429201FE7A
:100360008216022B0946010E0700660173FE181063
:10037000FE415809A4010EFEC8546BFE100301FE95
:100380008216022B2C4FFE02E82AFEBF57FE9E4328
:10039000FE7757FE27F0FEE001FE074BFE20F0A798
:1003A000FE401C1CD9FE26F0FE5A03FEA0F0FE48BB
:1003B00003FE11F0A7FEEF10FE9FF0FE6803F91098
:1003C000FE110002652CFE481CF908051BFE1813DF
:1003D0002122A3B713A30946010EB77801FEB41674
:1003E00012D11CD9FE01F0D9FE82F0FE9603FA125A
:1003F000FEE40027FEA8031C341DFEB803014BFEDB
:1004000006F0FEC8039586FE0AF0FE8A0602240363
:10041000702817FEFA04156D01367BFE6A0202D8B9
:10042000F92C9919FE671BFEBF57FE7757FE481C33
:100430007401AF8C0946010E070017DA09D1010ECD
:100440008D5164792A037028FE1012156D01367BD8
:10045000FE6A0202D8C781C8831C2427FE40041DFF
:10046000FE3C043BFEA000FE9B57FE4E122DFF02F9
:100470000010010B1DFEE4042D010B1D243331DEA1
:10048000FE4C44FE4C1251FE44480F6FFE4C546B20
:10049000DA4F792AFE0680FE4847FE621308051BE4
:1004A000FE2A13320782FE5213FE20100F6FFE4CFD
:1004B000546BDAFE0680FE4847FE401308051BFE1B
:1004C0000813320782FE301308051BFE1C12159D0F
:1004D0000805064D15FE0D0001367BFE640D022455
:1004E0002D12FEE600FE1C90FE405C04159D0136B8
:1004F000022BFE425B9919FE4659FEBF57FE775705
:10050000FE8780FE31E45B08050AFE8413FE20802E
:100510000719FE7C12530506FE6C1303FEA2002889
:1005200017FE9005FE31E45A53050AFE561303FEEA
:10053000A00028FE4E1267FF02001027FE48051C8F
:1005400034FE8948FF02001027FE560526FEA80546
:1005500012FEE3002153FE4AF0FE7605FE49F0FE4E
:1005600070058825FE2100AB25FE2200AA2558FE35
:100570000948FF02001027FE860526FEA805FEE2B8
:10058000085305CB4D01B0250613D339FE270108CA
:10059000051BFE22124101B2159D0805064D15FEF0
:1005A0000D0001367BFE640D022403FE9C0028EB47
:1005B000035C28FE36134101B226FE1806090653D5
:1005C000051FFE02125001FE9E151DFE0E0612A50D
:1005D000014B12FEE500035CC10C5C03CD28FE62FA
:1005E00012034528FE5A1301FE0C1901FE7619FE6E
:1005F0004348C4CC0F71FF02005752931E438BC473
:100600006E4101B226FE820653051AE9910959018D
:10061000FECC151DFE780612A5014B12FEE5000367
:1006200045C10C45180601B2FA767401AF8C12FE72
:10063000E20027DB1C34FE0AF0FEB60694FE6C07CF
:10064000FE06F0FE74079586022408050AFE2E12A7
:100650001619010B1600010B1600010B1600010BF9
:10066000FE99A4010B160002FE420868051AFE3826
:100670001208051AFE301316FE1B00010B160001AE
:100680000B1600010B1600010B1606010B160002DB
:10069000E26C58BE50FE9A81551B7AFE4207091B38
:1006A000FE096FBAFECA45FE3212696D8B6C7F2758
:1006B000FE54071C34FE0AF0FE4207958694FE6C39
:1006C000070224014B02DB161F02DBFE9CF7DCFE57
:1006D0002C90FEAE9056FEDA070C60146108545A56
:1006E0003722200711FE0E128DFE808039206A2AE3
:1006F000FE0610FE83E7FE4800ABFE034008545B95
:100700003701B3B8FE1F40136201EFFE0850FE8AA6
:1007100050FE4451FEC65188FE0890FE8A900C5E41
:10072000145FFE0C90FE8E90FE4050FEC2500C3DB9
:10073000143EFE4A1008055AFE2A12FE2C90FEAE08
:10074000900C60146108055B8B01B3FE1F8013627F
:10075000FE4490FEC6900C3F1440FE0890FE8A9026
:100760000C5E145FFE4090FEC2900C3D143E0C2EB9
:10077000143C210C490C6308541F372C0FFE4E11FA
:1007800027DDFE9EF0FE7608BC17342C77E6C5FE0A
:100790009A08C6FEB80894FE8E08FE06F0FE94087D
:1007A00095860224014BFEC910161FFEC91068056C
:1007B00006FE101268050A4E08050AFE9012FE2E6B
:1007C0001C02FE180B6805064E68050AFE7A12FE2A
:1007D0002C1CFEAAF0FED209FEACF0FE000902FEBF
:1007E000DE09FEB7F0FEFC08FE02F61A50FE701895
:1007F000FEF118FE4055FEE155FE1058FE9158FEE0
:100800001459FE95591C85FE8CF0FEFC08FEACF0D8
:10081000FEF008B5FECB10FEADF0FE0C0902FE188E
:100820000BB6FEBF10FE2BF085F41EFE00FEFE1C74
:1008300012C2FED2F085FE76181E19178503D21E4D
:10084000061785C54AC64AB5B6FE891074672D15C8
:100850009D013610FE3500FE01F06510800265FE38
:100860009880FE19E40AFE1A1251FE1982FE6C18D5
:10087000FE4454BEFE1981FE74188F9017FECE08F8
:10088000024A08055AEC032E293C0C3F14409B2ECB
:100890009C3CFE6C18FEED18FE4454FEE5543A3FB5
:1008A0003B40034929638FFEE354FE7418FEF5189C
:1008B0008FFEE35490C056FECE08024AFE37F0FE8B
:1008C000DA09FE8BF0FE6009024A08050A23FEFAE7
:1008D0000A3A493B6356FE3E0A0FFEC007419800A4
:1008E000ADFE0159FE52F0FE0C0A8F7AFE240A3A40
:1008F000498FFEE35457497D63FE1458FE95580214
:100900004A3A493B63FE1459FE9559BE574957630D
:10091000024A08055AFE821208051FFE661322626B
:10092000B7FE03A1FE8380FEC844FE2E13FE049191
:10093000FE86916A2AFE4059FEC15956E00360299D
:10094000610C7F148057607D6101B3B86A2A13621D
:100950009B2E9C3C3A3F3B4090C0FE04FA2EFE0585
:10096000FA3C01EFFE3610210C7F0C803A3F3B40F1
:10097000E408051F17E03A3D3B3E0805FEF7003747
:10098000035E295FFE1058FE915857497D6302FEB1
:10099000F40908051F17E00805FEF70037BEFE1929
:1009A0008150FE1090FE9290FED3103207A617FEE3
:1009B000080912A608050AFE1413033D293E56FE37
:1009C0000809FE0C58FE8D58024A2141FE1980E7A5
:1009D00008050AFE1A12FE6C19FE1941F4C2FED176
:1009E000F0E2157E013610FE4400FE8E10FE6C19FA
:1009F000573DFEED197D3EFE0C51FE8E51F41EFE5C
:100A000000FF35FE7410C2FED2F0FEA60BFE761873
:100A10001E198A03D21E06FE081310FE1600026578
:100A2000FED1F0FEB80B157E013610FE1700FE4217
:100A300010FECEF0FEBE0BFE3C10FECDF0FECA0B4B
:100A400010FE22000265FECBF0FED60B10FE240045
:100A50000265FED0F0FEE00B109EE5FECFF0FEEA50
:100A60000B1058FE1010FECCF0E268051F4D10FE72
:100A700012002C0FFE4E1127FE000CFE9EF0FE14FD
:100A80000CBC17342C77E6C524C6242CFA27FE208C
:100A90000C1C3494FE3C0C9586C5DCC6DC0224019B
:100AA0004BFEDB1012FEE800B5B674C781C883FEAA
:100AB00089F0243331E1C781C88327FE660C1D24E9
:100AC0003331DFBC4E10FE420002657C06FE8149D8
:100AD00017FE2C0D08050AFE44131000550AFE549B
:100AE0001255FE280023FE9A0D0946010E070066E6
:100AF00044FE2800FEE21001F501F609A401FE26DD
:100B00000F64122F0173022B10FE4400550AE944B2
:100B10000AFEB41001B0440AFEAA1001B0FE198208
:100B2000FE3446AC440A10FE4300FE961008540AF8
:100B30003701F501F664122F0173990A644292029B
:100B4000FE2E0308050A8A440A1000FE5C106805A0
:100B50001AFE581208051AFE5013FE1C1CFE9DF0CA
:100B6000FE500DFE1C1CFE9DF0FE560D08541A375B
:100B7000FEA91010FE1500FE04E60A50FE2E10100D
:100B8000FE1300FE1010106FAB10FE4100AA10FE05
:100B900024008CB5B67403702823D850FE04E61ADE
:100BA000FE9D41FE1C426401E3022BF8150A39A0A8
:100BB000B415FE310039A201FE481002D742FE06EC
:100BC000ECD0FC441BFECE453542FE06EAD0FE4783
:100BD0004B91FE7557035DFE9856FE381209480189
:100BE0000EFE44484F08051BFE1A130946010E412C
:100BF000FE415809A4010EFE495496FE1E0E02FE47
:100C00002E03095DFEEE14FC441BFECE453542FE6C
:100C1000CE47FEAD13022B22200711FE9E12211398
:100C200059139F13D5222F41392FBCADFEBCF0FEC6
:100C3000E00E0F06135901FEDA1603FE380129FEF5
:100C40003A0156FEE40EFE02ECD5690066FE04ECA5
:100C5000204FFE05F6FE340101FE4A17FE0890FE05
:100C600048F40DFE1813BAFE02EAD5697EFEC513DC
:100C7000151A39A0B4FE2E1003FE38011EFEF0FF37
:100C80000CFE600103FE3A010CFE620143132025B5
:100C900006132F122F920F060421042259FEF71279
:100CA000229FB7139F077EFE7113FE241C1519396E
:100CB000A0B4FED910C3FE03DCFE7357FE805D04B2
:100CC000C3FE03DCFE5B57FE805D04FE0357C321B9
:100CD000FE00CC04FE0357C37804080558FE221317
:100CE000FE1C800706FE1A13FE1E80EDFE1D80AE60
:100CF000FE0C90FE0E13FE0E90ACFE3C90FE30F407
:100D00000AFE3C50AA01FE7A1732072FAD01FEB44D
:100D10001608051B4E01F501F612FEE900080558FC
:100D2000FE2C1301FE0C17FE1E1CFE1490FE969066
:100D30000CFE640114FE660108055BFE1212FE0340
:100D4000808DFE01EC20FE804013206A2A12CF64C1
:100D50002220FB792004FE081C03FEAC00FE06588E
:100D600003FEAE00FE075803FEB000FE085803FE67
:100D7000B200FE0958FE0A1C256E13D0210C5C0C33
:100D8000450F465250181BFE904DFE915423FEFC19
:100D90000F44110F48521858FE904DFE915423E411
:100DA000251113207C6F4F2220FB792012CFFE14D7
:100DB00056FED6F0FE2610F874FE141CFE101CFE23
:100DC000181C0442FE0C14FCFE07E61BFECE47FE78
:100DD000F5130401B07C6F4FFE0680FE4847FE42CB
:100DE0001332072FFE34130948010EBBFE3612FEE4
:100DF0004148FE454801F0FE00CCBBFEF3134378AA
:100E00000711AC0984010EFE805C0173FE0E100711
:100E1000824EFE1456FED6F0FE601004FE44588D3D
:100E2000FE01ECA2FE9E40FE9DE700FE9CE71A79C3
:100E30002A01E3FEDD102CC781C8833331DE071A97
:100E4000FE4812070AFE56120719FE301207C9178C
:100E5000FE321207FE230017EB070617FE9C12074F
:100E60001FFE12120700172415C90136A92D010B08
:100E7000944B042DDD09D101FE260F1282022B2D89
:100E80003207A6FED9133A3D3B3E56FEF011080547
:100E90005AFE72129B2E9C3C90C096FEBA112262A2
:100EA000FE2613037F298056FE760D0C6014612107
:100EB0000C7F0C8001B3256E77136201EF9B2E9C93
:100EC0003CFE0455FEA555FE04FA2EFE05FA3CFE36
:100ED0009110033F2940FE4056FEE1560C3F14405E
:100EE000889B2E9C3C90C0035E295FFE0056FEA1AD
:100EF000560C5E145F08055AFE1E122262FE1F4049
:100F000003602961FE2C50FEAE50033F2940FE4491
:100F100050FEC650035E295FFE0850FE8A50033D16
:100F2000293EFE4050FEC2500289250613D40272AB
:100F30002D010B1D4C3331DE0706234C3207A6234F
:100F40007201AF1E43174C08050AEE3A3D3B3EFEC8
:100F50000A5535FE8B55573D7D3EFE0C51FE8E5198
:100F60000272FE1981BAFE194102722D010B1C3466
:100F70001DE83331E15519FEA612550A4D024C0108
:100F80000B1C341DE83331DF0719234C010B1DE81E
:100F90003331FEE809FEC2495103FE9C00288A5302
:100FA000051F35A9FEBB4555004E44067C43FEDABD
:100FB0001401AF8CFE4B45EE3207A5ED03CD288A18
:100FC00003452835670272FEC05DFEF814FE031764
:100FD000035CC10C5C672D010B268901FE9E150286
:100FE00089010B1C341D4C3331DF0706234C01F102
:100FF000FE4258F1FEA4148CFE4AF40A174CFE4A35
:10100000F406EA3207A58B02720345C10C45672D31
:10101000010B268901FECC1502890F0627FEBE139F
:1010200026FED41376FE8948010B2176047BFED080
:10103000131CFED0131DFEBE13672D010BFED51031
:101040000F71FF02005752931EFEFF7FFE3056FEC7
:10105000005C040F71FF02005752931E43FE30568E
:10106000FE005C040F71FF0200575293040F71FFE2
:101070000200575293FE0B5804095C018709450191
:101080008704FE03A11E11FF030054FE00F41F524B
:10109000FE007DFE017DFE027DFE037C6A2A0C5E61
:1010A000145F573F7D4004DDFE824AFEE11AFE8355
:1010B0005A8D0401FE0C19FE4248505191010B1D3E
:1010C000FE96153331E1010B1DFE96153331FEE816
:1010D0000AFEC15903CD28FECC1253051AFEC413D3
:1010E00021691AEE55CA6BFEDC144D0F0618CA7C36
:1010F00030FE7810FF028355ABFF0283556919AEAD
:1011000098FE300096F2186D0F06FE5610690AED33
:1011100098FE640096F209FE6400189E0F06FE28F1
:10112000106906FE601398FEC80096F209FEC8001A
:1011300018590F068898FE90017AFE421591E4FE38
:1011400043F49FFE56F0FE5415FE04F471FE43F482
:101150009EFEF310FE405C01FE16141E43ECFE00E2
:1011600017FE4DE46E7AFE9015C46EFE1C10FE0054
:1011700017FE4DE4CC7AFE9015C4CC885121FE4D6B
:10118000F400E9910F06FEB456FEC35804510F0A4D
:10119000041606010B26F3160A010B26F316190195
:1011A0000B26F376FE8949010B041606010B26B1C6
:1011B0001619010B26B11606010B26B1FE8949014D
:1011C0000B26B176FE894A010B04510422D307068F
:1011D000FE4813B813D3FE49F4004D76A967FE010B
:1011E000ECFE2701FE8948FF02001027FE2E163272
:1011F00007FEE300FE20131DFE52162113D4014BFF
:1012000022D407064E08540637040948010EFB8E07
:101210000711AE0984010E8E095D01A8040984013D
:101220000E8EFE80E71107118AFE455801F08E04EC
:101230000948010E8E095D01A8040948010EFE80CF
:1012400080FE804CFE49E411AE0984010EFE804C04
:10125000095D0187041811756CFE6001FE18DFFE40
:1012600019DEFE241CFE1DF71B97FEEE1601FEF490
:1012700017AD9A1B6CFE2C01FE2F1904B923FEDE5C
:1012800016FEDA1018117503FE6401FE00F41FFE4D
:10129000185803FE6601FE19589A1FFE3C90FE3056
:1012A000F406FE3C506CFE3800FE0F79FE1CF71F62
:1012B00097FE3817FEB6143504B923FE1017FE9CAE
:1012C00010181175FE835AFE18DFFE19DEFE1DF799
:1012D0002E97FE5A17FE9414EC9A2E6C1AFEAF1934
:1012E000FE98E70004B923FE4E17FE6C1018117526
:1012F000FE30BCFEB2BC9ACB6C1AFE0F79FE1CF716
:10130000CB97FE9217FE5C143504B923FE7E17FEC0
:101310004210FE02F61175FE18FE60FE19FE61FE17
:1013200003A1FE1DF75B97FEB817FE3614FE1C13D3
:101330009A5B41FE8358FEAF19FE80E711FE81E7FC
:101340001112FEDD006A2A046A2AFE124523FEA855
:1013500017150639A0B4022BFE39F0FEFC17210444
:10136000FE7E181E19660F0D047503D21E06FEEFD1
:1013700012FEE1107C6F4F32072FFE3C13F1FE424C
:101380001342920948010EBBEBFE4148FE4548015D
:10139000F0FE00CCBBFEF31343780711AC098401C7
:1013A0000EFE804C0173FE161007828BFE4014FE69
:1013B0002412FE1456FED6F0FE1C18180A04FE9CD9
:1013C000E70A10FE150064792A01E3180604429228
:1013D00008541B37122F0173180604FE3890FEBA0A
:1013E000903ACE3BCFFE485535FEC9550422A3772F
:1013F00013A30409A4010EFE41480946010EFE494B
:101400004417FEE8187778040948010E07114E09C1
:101410005D01A80946010E777804FE4EE4196BFEC3
:101420001C1903FE9000FE3A45FE2C10FE4EE4C946
:101430006BFE2E1903FE9200FE02E61AE5FE4EE454
:10144000FE0B006BFE401903FE9400FE02E61FFE39
:10145000081003FE9600FE02E66DFE4E45EABAFF56
:10146000046854E71E6EFE081CFE6719FE0A1CFE87
:101470001AF4FE0004EAFE48F4197AFE74190F19F2
:1014800004077EFE5AF0FE841925FE0900FE341082
:10149000071AFE5AF0FE921925CAFE261007196691
:1014A000256DE5070A66259EFE0E1007066625597E
:1014B000A9B80415FE09000136FE04FE810383FE6F
:1014C000405C041CF7FE14F00B27FED6191CF77BBA
:0C14D000F7FE82F0FEDA1904FFCC0000E9
:00000001FF
/* Microcode buffer is kept after initialization for error recovery. */

View file

@ -0,0 +1,398 @@
:1000000077EF0406000000F2001600FC001000F07C
:1000100018E40100041E48E403F6F7132E1E020044
:100020000717C05F00FAFFFF040000F609E782E748
:1000300085F086F04E109EE7FF0055F001F60300B4
:10004000985701E600EA00EC01FA18F40800F01DE8
:10005000385432F01000C20E1EF0D5F0BC004BE454
:1000600000E6B1F0B40002133E1CC8473E00D801C0
:1000700006130C1C5E1E0057C85701FCBC0EA212D2
:10008000B9540080620A5A12C8153E1E1840BD5667
:1000900003E601EA5CF00F0020006C016E0104121F
:1000A0000413BB553C563E5703584AE44000B60083
:1000B000BB00C000000101013E01580A44100A12B1
:1000C0004C1C4E1C024A30E405E60C003C0080004B
:1000D00024013C0168016A0170017201740176011A
:1000E00078017C01C60E0C10AC12AE12161A321C2E
:1000F0006E1E02483A55C95702EE5BF003F706F749
:1001000003FC06001E00BE00E1000C12181A701A53
:10011000301C381C1044004CB057405C4DE404EADD
:100120005DF0A7F004F602FC05000900190032009A
:1001300033003400360098009E00CC0020014E01B0
:1001400079013C09680D021004103A1008120A13D4
:100150004016501600174A19004E0054015800DC92
:1001600005F009F059F0B8F048F40EF70A009B00CA
:100170009C00A400B500BA00D000E700F0036908B5
:10018000E9095C0CB612BC19D81B201C341C361CA7
:10019000421D0844384491440A45484689486854F9
:1001A0008355835931E402E607F008F00BF00CF0B8
:1001B0004BF404F805F802FA03FA04FC05FC070006
:1001C000A800AA00B900E000E500220126016001B4
:1001D0007A018201C801CA0186026A031805B207C2
:1001E0006808100D06100A100E1012106010ED10A5
:1001F000F310061210121E120C130E131013FE9C95
:10020000F03505FEEC0EFF100000E9FE341F00E89B
:10021000FE8801FF030000FE9315FE0F05FF380066
:1002200000FE572400FE4C0065FF0400001AFF0981
:100230000000FF080101FF08FFFFFF270000FF107B
:10024000FFFFFF130000FE7856FE3412FF2100006E
:10025000FE04F7E8377D0D01FE4A11FE04F7E87D44
:100260000D5137FE3DF0FE0C02FE20F0BCFE91F079
:10027000FEF801FE90F0FEF801FE8FF0BC03674D22
:1002800005FE080F01FE780FFEDD1205FE0E03FECF
:10029000281C03FEA600FED1123E22FEA600ACFEE4
:1002A00048F0FE9002FE49F0FEAA02FE4AF0FEC8A7
:1002B00002FE46F0FE5A02FE47F0FE6002FE43F0E8
:1002C000FE4E02FE44F0FE5202FE45F0FE56021CB7
:1002D0000DA21C0722B70535FE001CFEF110FE0220
:1002E0001CF5FE1E1CFEE910015FFEE710FE06FC79
:1002F000DE0A8101A305351F9547B801FEE4110A06
:1003000081015CFEBD100A81015CFEAD10FE161C71
:10031000FE581C1C0722B7372A35FE3DF0FE0C02A2
:100320002BFE9E02FE5A1CFE121CFE141C1FFE30E9
:100330000047B801FED4111C0722B705E9212C099A
:100340001A31FE69101C0722B7FE04EC2C6001FE76
:100350001E1E202CFE05F6DE01FE621B010C614A0A
:100360004415565101FE9E1E01FE961A05350A5788
:1003700001180900360185FE1810FE41580ABA011D
:1003800018FEC8547BFE1C0301FE961A0535376023
:10039000FE02E830FEBF57FE9E43FE7757FE27F071
:1003A000FEE401FE074BFE20F0BCFE401C2AEBFEE3
:1003B00026F0FE6603FEA0F0FE5403FE11F0BCFE24
:1003C000EF10FE9FF0FE7403FE461C19FE1100059F
:1003D0007037FE481CFE461C010C0628FE1813262A
:1003E00021B9C720B90A570118C78901FEC81A15D3
:1003F000E12AEBFE01F0EBFE82F0FEA403FE9C324C
:1004000015FEE4002FFEB6032A3C16FEC60301418A
:10041000FE06F0FED603AFA0FE0AF0FEA2070529F5
:1004200003811E1BFE24051F6301428FFE7002051F
:10043000EAFE461C377D1DFE671BFEBF57FE775741
:10044000FE481C7501A6860A57011809001BEC0A14
:10045000E101187750408D3003811EF81F6301427F
:100460008FFE700205EAD799D89C2A292FFE4E04E8
:1004700016FE4A047EFEA000FE9B57FE541232FF79
:10048000020010010816FE02053201081629272570
:10049000EEFE4C44FE581250FE44481334FE4C54B9
:1004A0007BEC608D3001FE4E1EFE4847FE7C130142
:1004B0000C0628FE32130143099BFE6813FE26102A
:1004C0001334FE4C547BEC01FE4E1EFE4847FE5496
:1004D00013010C0628A50143099BFE4013010C06DD
:1004E00028F91F7F010C06074D1FFE0D0001428FEA
:1004F000FEA40E05293215FEE6000FFE1C9004FE38
:100500009C933A0B0E8B021F7F01420535FE425B26
:100510007D1DFE4659FEBF57FE77570FFE878004AC
:10052000FE8783FEC9470B0ED065010C060DFE98B1
:10053000130FFE208004FEA083330B0E091DFE84E2
:100540001201380607FE701303FEA2001E1BFEDA1E
:1005500005D0540138060DFE581303FEA0001EFE00
:1005600050125EFF0200102FFE90052A3CCCFF02C5
:1005700000102FFE9E0517FEF40515FEE300260170
:1005800038FE4AF0FEC005FE49F0FEBA05712EFEA7
:100590002100F12EFE2200A22E4AFE0948FF020091
:1005A000102FFED00517FEF405FEE208013806FE06
:1005B0001C004D01A72E0720E447FE2701010C0671
:1005C00028FE24123E01841F7F010C06074D1FFEEA
:1005D0000D0001428FFEA40E052903E61EFECA137C
:1005E00003B61EFE401203661EFE38133E0184173A
:1005F000FE72060A0701380624FE02124F01FE565B
:100600001916FE68061582014115E203668A106616
:10061000039A1EFE701203551EFE681301C60912CE
:1006200048FE92062E1201FEAC1DFE434862801366
:1006300058FF02005752AD233F4E62493E018417D6
:10064000FEEA0601380612F7450A9501FE841916DE
:10065000FEE0061582014115E203558A10551C077C
:100660000184FEAE10036F1EFE9E133E0184039AAA
:100670001EFE1A1201380612FC01C601FEAC1DFE58
:1006800043486280F0450A9503B61EF801380624F7
:1006900036FE02F60771788C004D62493E2D934E6E
:1006A000D00D17FE9A0701FEC01916FE90072620EE
:1006B0009E1582014115E2219E0907FB03E6FE58C3
:1006C0005710E605FE2A06036F8A106F1C07018487
:1006D000FE9C325F7501A68615FEE2002FED2A3CD6
:1006E000FE0AF0FECE07AEFE9608FE06F0FE9E085D
:1006F000AFA00529010C060DFE2E12141D010814D1
:100700000001081400010814000108FE99A4010862
:10071000140005FEC60901760612FE3A12010C0607
:1007200012FE301314FE1B0001081400010814000F
:1007300001081400010814070108140005EF7C4AA1
:10074000784F0FFE9A8104FE9A83FECB470B0E2D45
:100750002848FE6C080A28FE096FCAFECA45FE3208
:100760001253634E7C972FFE7E082A3CFE0AF0FE51
:100770006C08AFA0AEFE96080529014105ED1424D2
:1007800005EDFE9CF79F01FEAE1EFE185801FEBE51
:100790001EFE9958FE7818FEF9188EFE1609106A8A
:1007A000226B010C615444212C091AF87701FE7E5A
:1007B0001E472C7A30F0FE83E7FE3F0071FE0340B7
:1007C000010C61654401C2C8FE1F40206E01FE6A33
:1007D00016FE0850FE8A50FE4451FEC651FE10100F
:1007E00001FECE1E01FEDE1E1068226901FEEE1E15
:1007F00001FEFE1EFE4050FEC250104B224CFE8AEF
:1008000010010C0654FE501201FEAE1E01FEBE1E6B
:10081000106A226B010C06654E01C20FFE1F800498
:10082000FE9F83330B0E206E0FFE449004FEC49394
:100830003A0BFEC69004FEC693790B0E106C226D27
:1008400001FECE1E01FEDE1E106822690FFE4090E2
:1008500004FEC0933A0BFEC29004FEC293790B0EC5
:10086000104B224C10642234010C6124443713FED7
:100870004E112FFEDE09FE9EF0FEF209FE01481B1E
:100880003C3788F5D4FE1E0AD5FE420AD2FE1E0A67
:10089000D3FE420AAEFE120AFE06F0FE180AAFA010
:1008A00005290141FEC1101424FEC110017606077E
:1008B000FE14120176060D5D010C060DFE7412FE8B
:1008C0002E1C05FE1A0C017606075D0176060D4109
:1008D000FE2C1CFEAAF0FECE0AFEACF0FE660AFE5E
:1008E0009210C4F6FEADF0FE720A05FE1A0CC5FEAB
:1008F000E710FE2BF0BFFE6B1823FE00FEFE1C125D
:10090000ACFED2F0BFFE7618231D1BBF03E3230706
:100910001BBFD45BD55BD25BD35BC4C5FEA910758E
:100920005E321F7F014219FE3500FE01F0701998FA
:100930000570FE741823FE00F81B5B7D1201FE7823
:100940000F4D01FE961A2130777D1D055B010C06C7
:100950000D2BFEE20B010C0654FEA612010C062420
:10096000FE8813216EC701FE1E1F0FFE838004FE4A
:100970008383FEC9470B0EFEC844FE42130FFE04DC
:100980009104FE8493FECA570BFE869104FE869363
:10099000FECB570B0E7A30FE4059FEC1598E4003F4
:1009A0006A3B6B10972298D96ADA6B01C2C87A3019
:1009B000206EDB64DC34916C7E6DFE4455FEE555A3
:1009C000FE04FA64FE05FA3401FE6A16A3261097A7
:1009D0001098916C7E6DFE1410010C06241B409142
:1009E0004B7E4C010C06FEF7004403683B69FE1089
:1009F00058FE9158FE1459FE9559055B010C0624CA
:100A00001B40010C06FEF700447801FE8E1E4F0FBE
:100A1000FE109004FE90933A0BFE929004FE929387
:100A2000790B0EFEBD10014309BB1BFE6E0A15BB00
:100A3000010C060DFE1413034B3B4C8EFE6E0AFE9A
:100A40000C58FE8D58055B263E0FFE198004FE995A
:100A500083330B0EFEE510010C060DFE1A12FE6C20
:100A600019FE1941FE6B18ACFED1F0EF1F92014246
:100A700019FE4400FE9010FE6C19D94BFEED19DAF8
:100A80004CFE0C51FE8E51FE6B1823FE00FF31FE12
:100A90007610ACFED2F0FEBA0CFE7618231D5D0374
:100AA000E32307FE081319FE16000570FED1F0FEC1
:100AB000CC0C1F92014219FE17005CFECEF0FED254
:100AC0000CFE3E10FECDF0FEDE0C19FE220005707D
:100AD000FECBF0FEEA0C19FE24000570FED0F0FEFD
:100AE000F40C1994FE1C10FECFF0FEFE0C194AF314
:100AF000FECCF0EF017606244D19FE12003713FEEE
:100B00004E112FFE160DFE9EF0FE2A0DFE01481B13
:100B10003C3788F5D429D529D229D32937FE9C32F0
:100B20002FFE3E0D2A3CAEFE620DAFA0D49FD59F96
:100B3000D29FD39F05290141FED31015FEE800C4C2
:100B4000C575D799D89CFE89F0292725BED799D895
:100B50009C2FFE8C0D16292725BDFE0148A419FEE9
:100B6000420005709007FE81491BFE640E010C06D1
:100B70000DFE441319002D0DFE54122DFE28002BDE
:100B8000FEDA0E0A57011809003646FE2800FEFA62
:100B90001001FEF41C01FE001D0ABA01FE581040AF
:100BA00015560185053519FE44002D0DF7460DFE3D
:100BB000CC1001A7460DFEC21001A70FFE1982043A
:100BC000FE9983FECC470B0EFE3446A5460D19FE5A
:100BD0004300FEA210010C610D4401FEF41C01FE55
:100BE000001D40155601857D0D405101FE9E1E05DC
:100BF000FE3A03010C060D5D460D1900FE62100160
:100C0000760612FE5C12010C0612FE5213FE1C1C2C
:100C1000FE9DF0FE8E0EFE1C1CFE9DF0FE940E014D
:100C20000C611244FE9F1019FE1500FE04E60D4FE4
:100C3000FE2E1019FE1300FE101019FE4700F119C8
:100C4000FE4100A219FE240086C4C57503811E2B37
:100C5000EA4FFE04E612FE9D41FE1C424001F405EF
:100C600035FE121C1F0D47B5C31FFE310047B801EA
:100C7000FED41105E951FE06ECE0FE0E474628FEC3
:100C8000CE453151FE06EAE0FE474B45FE7557035F
:100C900067FE9856FE38120A5A0118FE4448600151
:100CA0000C0628FE18130A5701183EFE41580ABACE
:100CB000FEFA14FE4954B0FE5E0F05FE3A030A67C1
:100CC000FEE014FE0E474628FECE453151FECE47CB
:100CD000FEAD130535212C091AFE98122620962008
:100CE000E7FE081CFE7C19FEFD19FE0A1C03E5FE4A
:100CF0004855A53BFE6201FEC95531FE741001FE48
:100D0000F01A03FE38013BFE3A018EFE1E10FE0271
:100D1000ECE7530036FE04EC2C60FE05F6FE3401D1
:100D200001FE621B01FECE1EB211FE1813CAFE02A6
:100D3000EAE75392FEC3131F1247B5C3FE2A1003FE
:100D4000FE380123FEF0FF10E503FE3A0110FE62BB
:100D50000101FE1E1E202C155601FE9E1E130702C9
:100D600026022196C720960992FE79131F1D47B5CA
:100D7000C3FEE110CFFE03DCFE7357FE805D02CFA1
:100D8000FE03DCFE5B57FE805D02FE0357CF26FEAE
:100D900000CC02FE0357CF8902010C064AFE4E1317
:100DA0000FFE1C8004FE9C83330B0E0907FE3A13D2
:100DB0000FFE1E8004FE9E83330B0EFE2A130FFED1
:100DC0001D8004FE9D83FEF9130EFE1C1301FEEE32
:100DD0001EACFE141301FEFE1EFE8158FA01FE0E2B
:100DE0001FFE30F40DFE3C50A201FE921B01430990
:100DF00056FB01FEC81A010C0628A401FEF41C01D2
:100E0000FE001D15FEE900010C064AFE4E1301FE10
:100E1000221BFE1E1C0FFE149004FE94933A0BFE40
:100E2000969004FE9693790B0E10FE640122FE66E6
:100E300001010C0665F90FFE038004FE8383330B6A
:100E40000E77FE01EC2CFE8040202C7A3015DF401E
:100E5000212CFE00408D2C02FE081C03FEAC00FE7F
:100E6000065803FEAE00FE075803FEB000FE085809
:100E700003FEB200FE0958FE0A1C2E4920E026108F
:100E8000661055106F1357524F1C28FE904DFE915F
:100E9000542BFE8811461A135A521C4AFE904DFEDE
:100EA00091542BFE9E112E1A202C903460212CFE82
:100EB00000408D2C15DFFE1456FED6F0FEB211FE5A
:100EC000121C75FE141CFE101CFE181C0251FE0C98
:100ED00014FE0E47FE07E628FECE47FEF51302017C
:100EE000A7903460FE0680FE4847FE4213FE028053
:100EF0000956FE34130A5A0118CBFE3612FE414839
:100F0000FE454801FEB216FE00CCCBFEF3133F892E
:100F1000091AA50A9D0118FE805C0185F2099BA4AF
:100F2000FE1456FED6F0FEEC1102FE445877FE0188
:100F3000ECB8FE9E40FE9DE700FE9CE7128D30015E
:100F4000F4FEDD1037D799D89C2725EE0912FE480C
:100F500012090DFE5612091DFE301209DD1BFEC4DA
:100F60001309FE23001BFED01309071BFE341409CE
:100F700024FE121209001B291FDD0142A1320108C3
:100F8000AE410232FE62080AE101FE5810159B05CF
:100F90003532014309BBFED713914B7E4C8EFE8048
:100FA00013010C0654FE7212DB64DC34FE4455FE61
:100FB000E555B0FE4A13216EFE261303973B988E2B
:100FC000FEB60E106A226B261097109801C22E49A9
:100FD00088206E01FE6A16DB64DC34FE0455FEA533
:100FE00055FE04FA64FE05FA34FE8F10036C3B6D67
:100FF000FE4056FEE156106C226D71DB64DC34FE5F
:101000004455FEE55503683B69FE0056FEA15610A7
:10101000682269010C0654F9216EFE1F40036A3BE9
:101020006BFE2C50FEAE50036C3B6DFE4450FEC672
:101030005003683B69FE0850FE8A50034B3B4CFE50
:101040004050FEC25005732E07209E0572320108E3
:10105000163D2725EE09072B3D014309BB2B7201E5
:10106000A6233F1B3D010C060DFE1E13914B7E4C2B
:10107000FE0A5531FE8B55D94BDA4CFE0C51FE8ED3
:1010800051057201FE8E1ECAFE1941057232010819
:101090002A3C16C02725BE2D1DC02D0D832D7F1B7C
:1010A000FE6615053D01082A3C16C02725BD091D11
:1010B0002B3D010816C02725FEE809FEC249500352
:1010C000B61E830138062431A1FEBB452D00A4467F
:1010D00007903F01FEF81501A686FE4B45FE201342
:1010E00001430982FE1613039A1E5D03551E315EED
:1010F0000572FEC05D01A7FE031703668A10665ED7
:10110000320108177301FE5619057301082A3C16AF
:101110003D2725BD09072B3D01FEBE16FE4258FEA8
:10112000E81401A686FE4AF40D1B3DFE4AF407FEB4
:101130000E12014309824E057203558A10555E3224
:101140000108177301FE8419057301082A3C163D36
:101150002725BD09122B3D01FEE8178BFEAA14FEC0
:10116000B61486A8B20D1B3DB207FE0E120143094C
:10117000824E0572036F8A106F5E32010817730189
:10118000FEC019057313072FFECC1517FEE2155F7D
:10119000CC0108265F028FFEDE152AFEDE1516FE44
:1011A000CC155E320108FED5101358FF02005752CD
:1011B000AD23FEFF7FFE3056FE005C021358FF0297
:1011C000005752AD233FFE3056FE005C021358FF1D
:1011D00002005752AD021358FF02005752FE005E44
:1011E000021358FF02005752ADFE0B58020A660167
:1011F0005C0A55015C0A6F015C0201FE1E1F231A86
:10120000FF030054FE00F424520FFE007C04FE078E
:101210007C3A0B0EFE0071FEF918FE7A19FEFB19DE
:10122000FE1AF700FE1BF7007A3010682269D96CAD
:10123000DA6D02FE6208FE824AFEE11AFE835A77E8
:101240000201C6FE42484F5045010816FEE017272E
:1012500025BE010816FEE0172725FEE80AFEC15943
:10126000039A1EFEDA1201380612FED0132653121C
:1012700048FE0817D1125312FE1E132DB47BFE2612
:10128000174D13071CB49004FE7810FF028355F12C
:10129000FF028355531DFE1213D6FE3000B0FE80B0
:1012A000171C631307FE5610530DFE1613D6FE646B
:1012B00000B0FE80170AFE64001C941307FE28107D
:1012C0005307FE6013D6FEC800B0FE80170AFEC8A2
:1012D000001C95130771D6FE900148FE8C1745F34C
:1012E000FE43F496FE56F0FE9E17FE04F458FE43AD
:1012F000F494F68B01FE2416233FFCA88C4948FE8B
:10130000DA176249FE1C10A88C8048FEDA1762804A
:10131000715026FE4DF400F7451307FEB456FEC388
:10132000580250130D02503E784F45010816A92768
:1013300025BEFE03EAFE7E01010816A92725FEE967
:101340000A010816A92725FEE90AFE05EAFE7F0123
:10135000010816A92725FE6909FE02EAFE8001019F
:101360000816A92725FEE80847FE810103B61E835B
:101370000138062431A278F2530736FE34F43FA137
:1013800078039A1E830138061231F04F45FE901003
:10139000FE405A233FFB8C4948FEAA186249718CD3
:1013A0008048FEAA186280FEB456FE405D01C60168
:1013B000FEAC1DFE0217FEC845FE5AF0FEC018FE28
:1013C00043482D9336FE34F4FE0011FE40102DB438
:1013D00036FE34F404FE34102DFE0B00364663FE58
:1013E0002810FEC049FF020054B2FE900148FEFAE8
:1013F0001845FE1CF43FF3FE40F496FE56F0FE0C3A
:1014000019FE04F458FE40F494F63E2D934ED00D90
:1014100021FE7F01FEC846FE24138C005D2621FEBE
:101420007E01FEC845FE141321FE8001FE4845FAE8
:1014300021FE8101FEC8444E260213070278455062
:10144000130D021407010817FE8219140D01081765
:10145000FE8219141D010817FE82195FFE894901D9
:1014600008021407010817C1141D010817C1140749
:10147000010817C1FE8949010817C15FFE894A01A9
:1014800008025002140701081774147F010817742A
:10149000141201081774FE89490108177414000119
:1014A000081774FE894A01081774FE0949010817D4
:1014B000745FCC01080221E40907FE4C13C820E444
:1014C000FE49F4004D5FA15EFE01ECFE2701CCFF5A
:1014D0000200102FFE3E1A014309FEE300FE221314
:1014E00016FE641A26209E0141219E09075D010C0B
:1014F000610744020A5A0118FE0040AA091AFE12A6
:10150000130A9D0118AA0A6701A3020A9D0118AADD
:10151000FE80E71A091A5DFE455801FEB216AA02BE
:101520000A5A0118AA0A6701A3020A5A011801FE01
:101530007E1EFE804CFE49E41AFE12130A9D01181D
:10154000FE804C0A67015C021C1A877CE5FE18DFEE
:10155000FE19DEFE241CFE1DF728B1FE041B01FE51
:101560002A1CFAB3287CFE2C01FE2F1902C92BFE7F
:10157000F41AFEFA101C1A8703FE6401FE00F4241C
:10158000FE185803FE6601FE1958B32401FE0E1F13
:10159000FE30F407FE3C507CFE3800FE0F79FE1C46
:1015A000F724B1FE501BFED4143102C92BFE261BBA
:1015B000FEBA101C1A87FE835AFE18DFFE19DEFEE3
:1015C0001DF754B1FE721BFEB214FCB3547C12FE24
:1015D000AF19FE98E70002C92BFE661BFE8A101C9D
:1015E0001A878B0FFE309004FEB0933A0BFE18580A
:1015F000FE329004FEB2933A0BFE19580EA8B34A7D
:101600007C12FE0F79FE1CF74AB1FEC61BFE5E146B
:101610003102C92BFE961B5CFE02F61A87FE18FEED
:101620006AFE19FE6B01FE1E1FFE1DF765B1FEEE80
:101630001BFE3614FE1C13B3653EFE8358FEAF1925
:10164000FE80E71AFE81E71A15FEDD007A30027A85
:1016500030FE12452BFEDC1B1F0747B5C30535FEC8
:1016600039F0752602FE7E18231D361311028703FA
:10167000E32307FEEF12FEE110903460FE028009C2
:1016800056FE3C13FE8214FE421351FE06830A5A94
:101690000118CBFE3E12FE4148FE454801FEB2163F
:1016A000FE00CCCBFEF3133F89091AA50A9D011851
:1016B000FE804C0185FE1610099B4EFE4014FE2450
:1016C00012FE1456FED6F0FE521C1C0D02FE9CE7C4
:1016D0000D19FE1500408D3001F41C070251FE0665
:1016E00083FE1880612844155601851C0702FE38C8
:1016F00090FEBA9091DE7EDFFE485531FEC955025C
:1017000021B98820B9020ABA0118FE41480A5701D6
:1017100018FE49441BFE1E1D8889020A5A01180939
:101720001AA40A6701A30A570118888902FE4EE429
:101730001D7BFE521D03FE9000FE3A45FE2C10FE5E
:101740004EE4DD7BFE641D03FE9200D112FE1A10F2
:10175000FE4EE4FE0B007BFE761D03FE9400D124BA
:10176000FE081003FE9600D163FE4E4583CAFF04B7
:101770006854FEF1102349FE081CFE6719FE0A1C7E
:10178000FE1AF4FE000483B21D48FEAA1D131D02BA
:101790000992FE5AF0FEBA1D2E93FE34100912FE75
:1017A0005AF0FEC81D2EB4FE2610091D362E63FE0B
:1017B0001A10090D362E94F20907362E95A1C8028B
:1017C0001F930142FE04FE99039C8B022AFE1C1EFD
:1017D000FE14F0082FFE0C1E2AFE1C1E8FFE1C1E7F
:1017E000FE82F0FE101E020F3F04FE8083330B0EBC
:1017F000020FFE188004FE9883330B0E020FFE02C8
:101800008004FE8283330B0E020FFE068004FE86E8
:1018100083330B0E020FFE1B8004FE9B83330B0EE3
:10182000020FFE048004FE8483330B0E020FFE8041
:101830008004FE8083FEC9470B0E020FFE1981044F
:10184000FE9983FECA470B0E020FFE068304FE8636
:1018500083FECE470B0E020FFE2C9004FEAC933A93
:101860000B0E020FFEAE9004FEAE93790B0E020F2C
:10187000FE089004FE88933A0B0E020FFE8A900435
:10188000FE8A93790B0E020FFE0C9004FE8C933AA5
:101890000B0E020FFE8E9004FE8E93790B0E020F3C
:1018A000FE3C9004FEBC933A0B0E028B0FFE0380AD
:0E18B00004FE8383330B770EA802FF66000050
:00000001FF
/* Microcode buffer is kept after initialization for error recovery. */

View file

@ -0,0 +1,147 @@
:100000003F452C01010301190F0000000000000012
:10001000000000000F0F0F0F0F0F0F0F0000000068
:1000200000000000000000000000000000000000D0
:1000300000000000000000000000000000000000C0
:100040000000000000000000C3120D0501000000C8
:1000500000FF000000000000FF80FFFF0100000023
:10006000000000000000002300000000000700FF67
:1000700000000000FFFFFF00000000000000E48817
:100080000000000080734804360000A2C2008073A4
:1000900003233640B600360005D60CD212DA00A291
:1000A000C20092801E985000F5004898DF23366009
:1000B000B60092804F00F5004898EF233660B600F6
:1000C000928080629280004615EE13EA020109D800
:1000D000CD044D0000A3D600A6977F2304618401C0
:1000E000E684D2C18073CD044D0000A3DA01A69747
:1000F000C681C28880738077000101A1FE004F0095
:10010000849707A6080100330300C288030301DEB9
:10011000C288CE006960CE0002034A6000A2780166
:10012000806307A62401788103038063E20007A6A9
:10013000340100330400C2880307020104CA0D23FE
:1001400068984D04048505D80D236898CD041523BF
:10015000F888FB23026182018063020306A3620127
:1001600000330A00C2884E0007A36E0100330B0063
:10017000C288CD04362D00331A00C288500488810D
:1001800006AB820188814E0007A39201500000A3B4
:100190003C0100057C814697020105C60423A001AD
:1001A0001523A101BE81FD23026182010ADA4A0002
:1001B000066100A0B4018063CD04362D00331B001E
:1001C000C28806236898CD04E684060100A2D40103
:1001D000576000A0DA01E6848023A001E6848073E2
:1001E0004B00066100A2000204010CDE020103CCF8
:1001F0004F008497FC810823024182014F006297DF
:1002000048048480F0970046560003C00123E800AC
:1002100081730629034206E203EE6BEB1123F88893
:100220000498F0808073807707A42A027C9506A644
:10023000340203A64C044682040103D8B4986A969B
:100240004682FE95806783038063B62D02A66C020A
:1002500007A65A0206A65E0203A66202C2887C9521
:100260004882609648820423A0011423A1013C84A3
:1002700004010CDCE0232561EF0014014F04A80108
:100280006F00A5010323A40106239C01242B1C015C
:1002900002A6AA0207A65A0206A65E0203A6200428
:1002A00001A6B40200A6B40200331200C288000EF8
:1002B0008063004300A08C024D0404010BDCE723A3
:1002C00004618401103112351401EC006C38003FD8
:1002D0000000EA821823046118A0E2020401A2C807
:1002E00000331F00C28808310A350C390E3D7E9854
:1002F000B62D01A6140300A6140307A60C0306A638
:10030000100303A6200402A66C0200333300C28847
:100310007C95EE826096EE82829880427E9864E4BC
:1003200004012DC83105070100A2540300438701D1
:10033000050586987E9800A6160307A64C0303A61B
:100340003C0406A6500301A6160300332500C2880C
:100350007C95328360963283040110CE07C8050570
:10036000EB0400330020C020816272830001050588
:10037000FFA27A03B1010823B2012E8305051501FE
:1003800000A29A03EC006E0095016C38003F00005B
:1003900001A6960300A69603108480427E9801A6CB
:1003A000A40300A6BC031084A898804201A6A4035D
:1003B00007A6B203D4837C95A88300332F00C2889C
:1003C000A898804200A6BC0307A6CA03D4837C95E4
:1003D000C08300332600C288382B80328036042345
:1003E000A0011223A101108407F006A4F403806B7E
:1003F000806705238303806303A60E0407A6060413
:1004000006A60A0400331700C2887C95F483609620
:10041000F483208407F006A42004806B8067052302
:1004200083038063B62D03A63C0407A6340406A606
:10043000380400333000C2887C9520846096208484
:100440001D0106CC00330084C0200023EA00816235
:10045000A20D806307A65A0400331800C288030364
:100460008063A30107A46404230100A286040AA0F8
:100470007604E00000331D00C2880BA08204E00077
:1004800000331E00C2884223F888002322A3E6041A
:10049000082322A3A204282322A3AE04022322A31A
:1004A000C4044223F8884A00066100A0AE04452334
:1004B000F888049800A2C004B49800330082C020D9
:1004C0008162E8814723F88804010BDE0498B49820
:1004D00000330081C0208162140100A00002432388
:1004E000F8880423A0014423A10180734D0003A3D5
:1004F000F40400332700C288040104DC0223A201B3
:100500000423A001049826954B00F6004F044F00E9
:1005100000A3220500057600066100A21C050A85DD
:100520004697CD04248548048480020103DA8023A1
:10053000820134850223A0014A00066100A2400521
:100540001D0104D6FF2386414B60CB00FF238001B1
:1005500049008101040102C830018001F704030150
:1005600049048001C90000050001FFA0600577046F
:100570000123EA005D00FEC700620023EA00006379
:1005800007A4F805030302A08E05F48500332D00AF
:10059000C28804A0B80580630023DF004A0006611A
:1005A00000A2A4051D0106D60223024182015000CB
:1005B00062970485042302418201048508A0BE05D8
:1005C000F48503A0C405F48501A0CE0588008063EE
:1005D000CC8607A0EE055F00002BDF0800A2E60531
:1005E0008067806301A27A067C8506236898482389
:1005F000F88807238000068780637C850023DF005E
:1006000000634A00066100A236061D0116D4C0230D
:1006100007418303806306A61C0600333700C288A7
:100620001D0101D620236360830380630223DF0062
:1006300007A67C05EF046F0000634B000641CB006A
:100640005200066100A24E061D0103CAC0230741E5
:1006500000631D0104CC00330083C020816280232D
:1006600007410063806708238303806300630123DD
:10067000DF0006A6840607A67C058067806300333A
:100680000040C020816200630000FE958303806308
:1006900006A6940607A67C05000001A01407002BFF
:1006A000400E8063010006A6AA0607A67C05400E40
:1006B0008063004300A0A20606A6BC0607A67C0530
:1006C0008067400E806307A67C050023DF0000637F
:1006D00007A6D60600332A00C28803038063890078
:1006E0000A2B07A6E80600332900C288004300A2AF
:1006F000F406C00E8063DE86C00E00330080C0208A
:100700008162040102DA80637C85807B806306A6B7
:100710008C0600332C00C2880CA22E07FE958303A2
:10072000806306A62C0707A67C0500333D00C2881F
:1007300000008067830380630CA0440707A67C0544
:10074000BF2304618401E6840063F0040101F10029
:100750000001F20001058001720471008101700442
:10076000800581050063F004F20072040101F100CC
:1007700070008101700471008101720080017104B8
:100780007000800170040063F004F2007204000144
:10079000F10070008001700471008001720081011D
:1007A000710470008101700400630023B3018305AC
:1007B000A301A201A1010123A0010001C80003A11E
:1007C000C40700330700C28880058105040111C8F1
:1007D0004800B001B1010823B201050148040043FB
:1007E00000A2E4070005DA870001C800FF238001AA
:1007F00005050063F7041A09F6086E040002804339
:100800007608800277040063F7041A09F6086E047C
:10081000000200A0140816880043760880027704BE
:100820000063F3040023F40074008043F400CF401D
:1008300000A2440874040201F7C9F6D9000101A11D
:10084000240804982695248873040063F30475042F
:100850005A88020104D84697049826954A8875005C
:1008600000A3640800054E8873040063807B8063E6
:1008700006A6760800333E00C28880678303806343
:100880000063382B9C88382B928832093105929866
:100890000505B209006300320036003A003E0063ED
:1008A00080328036803A803EB43D0063382B40323F
:1008B0004036403A403E00635A20C94000A0B40888
:1008C0005D00FEC300638073E6200223E8008273AC
:1008D000FFFD80731323F8886620C0200423A00145
:1008E000A123A1018162E28880738077680000A261
:1008F000800003C2F1C74123F8881123A10104231A
:04090000A001E684E8
:00000001FF
/* Microcode buffer is kept after initialization for error recovery. */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

237
include/scsi/fc/fc_fip.h Normal file
View file

@ -0,0 +1,237 @@
/*
* Copyright 2008 Cisco Systems, Inc. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _FC_FIP_H_
#define _FC_FIP_H_
/*
* This version is based on:
* http://www.t11.org/ftp/t11/pub/fc/bb-5/08-543v1.pdf
*/
/*
* The FIP ethertype eventually goes in net/if_ether.h.
*/
#ifndef ETH_P_FIP
#define ETH_P_FIP 0x8914 /* FIP Ethertype */
#endif
#define FIP_DEF_PRI 128 /* default selection priority */
#define FIP_DEF_FC_MAP 0x0efc00 /* default FCoE MAP (MAC OUI) value */
#define FIP_DEF_FKA 8000 /* default FCF keep-alive/advert period (mS) */
#define FIP_VN_KA_PERIOD 90000 /* required VN_port keep-alive period (mS) */
#define FIP_FCF_FUZZ 100 /* random time added by FCF (mS) */
/*
* Multicast MAC addresses. T11-adopted.
*/
#define FIP_ALL_FCOE_MACS ((u8[6]) { 1, 0x10, 0x18, 1, 0, 0 })
#define FIP_ALL_ENODE_MACS ((u8[6]) { 1, 0x10, 0x18, 1, 0, 1 })
#define FIP_ALL_FCF_MACS ((u8[6]) { 1, 0x10, 0x18, 1, 0, 2 })
#define FIP_VER 1 /* version for fip_header */
struct fip_header {
__u8 fip_ver; /* upper 4 bits are the version */
__u8 fip_resv1; /* reserved */
__be16 fip_op; /* operation code */
__u8 fip_resv2; /* reserved */
__u8 fip_subcode; /* lower 4 bits are sub-code */
__be16 fip_dl_len; /* length of descriptors in words */
__be16 fip_flags; /* header flags */
} __attribute__((packed));
#define FIP_VER_SHIFT 4
#define FIP_VER_ENCAPS(v) ((v) << FIP_VER_SHIFT)
#define FIP_VER_DECAPS(v) ((v) >> FIP_VER_SHIFT)
#define FIP_BPW 4 /* bytes per word for lengths */
/*
* fip_op.
*/
enum fip_opcode {
FIP_OP_DISC = 1, /* discovery, advertisement, etc. */
FIP_OP_LS = 2, /* Link Service request or reply */
FIP_OP_CTRL = 3, /* Keep Alive / Link Reset */
FIP_OP_VLAN = 4, /* VLAN discovery */
FIP_OP_VENDOR_MIN = 0xfff8, /* min vendor-specific opcode */
FIP_OP_VENDOR_MAX = 0xfffe, /* max vendor-specific opcode */
};
/*
* Subcodes for FIP_OP_DISC.
*/
enum fip_disc_subcode {
FIP_SC_SOL = 1, /* solicitation */
FIP_SC_ADV = 2, /* advertisement */
};
/*
* Subcodes for FIP_OP_LS.
*/
enum fip_trans_subcode {
FIP_SC_REQ = 1, /* request */
FIP_SC_REP = 2, /* reply */
};
/*
* Subcodes for FIP_OP_RESET.
*/
enum fip_reset_subcode {
FIP_SC_KEEP_ALIVE = 1, /* keep-alive from VN_Port */
FIP_SC_CLR_VLINK = 2, /* clear virtual link from VF_Port */
};
/*
* Subcodes for FIP_OP_VLAN.
*/
enum fip_vlan_subcode {
FIP_SC_VL_REQ = 1, /* request */
FIP_SC_VL_REP = 2, /* reply */
};
/*
* flags in header fip_flags.
*/
enum fip_flag {
FIP_FL_FPMA = 0x8000, /* supports FPMA fabric-provided MACs */
FIP_FL_SPMA = 0x4000, /* supports SPMA server-provided MACs */
FIP_FL_AVAIL = 0x0004, /* available for FLOGI/ELP */
FIP_FL_SOL = 0x0002, /* this is a solicited message */
FIP_FL_FPORT = 0x0001, /* sent from an F port */
};
/*
* Common descriptor header format.
*/
struct fip_desc {
__u8 fip_dtype; /* type - see below */
__u8 fip_dlen; /* length - in 32-bit words */
};
enum fip_desc_type {
FIP_DT_PRI = 1, /* priority for forwarder selection */
FIP_DT_MAC = 2, /* MAC address */
FIP_DT_MAP_OUI = 3, /* FC-MAP OUI */
FIP_DT_NAME = 4, /* switch name or node name */
FIP_DT_FAB = 5, /* fabric descriptor */
FIP_DT_FCOE_SIZE = 6, /* max FCoE frame size */
FIP_DT_FLOGI = 7, /* FLOGI request or response */
FIP_DT_FDISC = 8, /* FDISC request or response */
FIP_DT_LOGO = 9, /* LOGO request or response */
FIP_DT_ELP = 10, /* ELP request or response */
FIP_DT_VN_ID = 11, /* VN_Node Identifier */
FIP_DT_FKA = 12, /* advertisement keep-alive period */
FIP_DT_VENDOR = 13, /* vendor ID */
FIP_DT_VLAN = 14, /* vlan number */
FIP_DT_LIMIT, /* max defined desc_type + 1 */
FIP_DT_VENDOR_BASE = 128, /* first vendor-specific desc_type */
};
/*
* FIP_DT_PRI - priority descriptor.
*/
struct fip_pri_desc {
struct fip_desc fd_desc;
__u8 fd_resvd;
__u8 fd_pri; /* FCF priority: higher is better */
} __attribute__((packed));
/*
* FIP_DT_MAC - MAC address descriptor.
*/
struct fip_mac_desc {
struct fip_desc fd_desc;
__u8 fd_mac[ETH_ALEN];
} __attribute__((packed));
/*
* FIP_DT_MAP - descriptor.
*/
struct fip_map_desc {
struct fip_desc fd_desc;
__u8 fd_resvd[3];
__u8 fd_map[3];
} __attribute__((packed));
/*
* FIP_DT_NAME descriptor.
*/
struct fip_wwn_desc {
struct fip_desc fd_desc;
__u8 fd_resvd[2];
__be64 fd_wwn; /* 64-bit WWN, unaligned */
} __attribute__((packed));
/*
* FIP_DT_FAB descriptor.
*/
struct fip_fab_desc {
struct fip_desc fd_desc;
__be16 fd_vfid; /* virtual fabric ID */
__u8 fd_resvd;
__u8 fd_map[3]; /* FC-MAP value */
__be64 fd_wwn; /* fabric name, unaligned */
} __attribute__((packed));
/*
* FIP_DT_FCOE_SIZE descriptor.
*/
struct fip_size_desc {
struct fip_desc fd_desc;
__be16 fd_size;
} __attribute__((packed));
/*
* Descriptor that encapsulates an ELS or ILS frame.
* The encapsulated frame immediately follows this header, without
* SOF, EOF, or CRC.
*/
struct fip_encaps {
struct fip_desc fd_desc;
__u8 fd_resvd[2];
} __attribute__((packed));
/*
* FIP_DT_VN_ID - VN_Node Identifier descriptor.
*/
struct fip_vn_desc {
struct fip_desc fd_desc;
__u8 fd_mac[ETH_ALEN];
__u8 fd_resvd;
__u8 fd_fc_id[3];
__be64 fd_wwpn; /* port name, unaligned */
} __attribute__((packed));
/*
* FIP_DT_FKA - Advertisement keep-alive period.
*/
struct fip_fka_desc {
struct fip_desc fd_desc;
__u8 fd_resvd[2];
__be32 fd_fka_period; /* adv./keep-alive period in mS */
} __attribute__((packed));
/*
* FIP_DT_VENDOR descriptor.
*/
struct fip_vendor_desc {
struct fip_desc fd_desc;
__u8 fd_resvd[2];
__u8 fd_vendor_id[8];
} __attribute__((packed));
#endif /* _FC_FIP_H_ */

View file

@ -1,54 +0,0 @@
#ifndef FC_TRANSPORT_FCOE_H
#define FC_TRANSPORT_FCOE_H
#include <linux/device.h>
#include <linux/netdevice.h>
#include <scsi/scsi_host.h>
#include <scsi/libfc.h>
/**
* struct fcoe_transport - FCoE transport struct for generic transport
* for Ethernet devices as well as pure HBAs
*
* @name: name for thsi transport
* @bus: physical bus type (pci_bus_type)
* @driver: physical bus driver for network device
* @create: entry create function
* @destroy: exit destroy function
* @list: list of transports
*/
struct fcoe_transport {
char *name;
unsigned short vendor;
unsigned short device;
struct bus_type *bus;
struct device_driver *driver;
int (*create)(struct net_device *device);
int (*destroy)(struct net_device *device);
bool (*match)(struct net_device *device);
struct list_head list;
struct list_head devlist;
struct mutex devlock;
};
/**
* MODULE_ALIAS_FCOE_PCI
*
* some care must be taken with this, vendor and device MUST be a hex value
* preceded with 0x and with letters in lower case (0x12ab, not 0x12AB or 12AB)
*/
#define MODULE_ALIAS_FCOE_PCI(vendor, device) \
MODULE_ALIAS("fcoe-pci-" __stringify(vendor) "-" __stringify(device))
/* exported funcs */
int fcoe_transport_attach(struct net_device *netdev);
int fcoe_transport_release(struct net_device *netdev);
int fcoe_transport_register(struct fcoe_transport *t);
int fcoe_transport_unregister(struct fcoe_transport *t);
int fcoe_load_transport_driver(struct net_device *netdev);
int __init fcoe_transport_init(void);
int __exit fcoe_transport_exit(void);
/* fcow_sw is the default transport */
extern struct fcoe_transport fcoe_sw_transport;
#endif /* FC_TRANSPORT_FCOE_H */

View file

@ -22,6 +22,7 @@
#include <linux/timer.h>
#include <linux/if.h>
#include <linux/percpu.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
@ -661,7 +662,8 @@ struct fc_lport {
unsigned long boot_time;
struct fc_host_statistics host_stats;
struct fcoe_dev_stats *dev_stats[NR_CPUS];
struct fcoe_dev_stats *dev_stats;
u64 wwpn;
u64 wwnn;
u8 retry_count;
@ -694,11 +696,6 @@ struct fc_lport {
/*
* FC_LPORT HELPER FUNCTIONS
*****************************/
static inline void *lport_priv(const struct fc_lport *lp)
{
return (void *)(lp + 1);
}
static inline int fc_lport_test_ready(struct fc_lport *lp)
{
return lp->state == LPORT_ST_READY;
@ -722,6 +719,42 @@ static inline void fc_lport_state_enter(struct fc_lport *lp,
lp->state = state;
}
static inline int fc_lport_init_stats(struct fc_lport *lp)
{
/* allocate per cpu stats block */
lp->dev_stats = alloc_percpu(struct fcoe_dev_stats);
if (!lp->dev_stats)
return -ENOMEM;
return 0;
}
static inline void fc_lport_free_stats(struct fc_lport *lp)
{
free_percpu(lp->dev_stats);
}
static inline struct fcoe_dev_stats *fc_lport_get_stats(struct fc_lport *lp)
{
return per_cpu_ptr(lp->dev_stats, smp_processor_id());
}
static inline void *lport_priv(const struct fc_lport *lp)
{
return (void *)(lp + 1);
}
/**
* libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport
* @sht: ptr to the scsi host templ
* @priv_size: size of private data after fc_lport
*
* Returns: ptr to Scsi_Host
*/
static inline struct Scsi_Host *
libfc_host_alloc(struct scsi_host_template *sht, int priv_size)
{
return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size);
}
/*
* LOCAL PORT LAYER

View file

@ -1,5 +1,6 @@
/*
* Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
* Copyright (c) 2008-2009 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2007-2008 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -20,134 +21,144 @@
#ifndef _LIBFCOE_H
#define _LIBFCOE_H
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <scsi/fc/fc_fcoe.h>
#include <scsi/libfc.h>
/*
* this percpu struct for fcoe
* FIP tunable parameters.
*/
struct fcoe_percpu_s {
int cpu;
struct task_struct *thread;
struct sk_buff_head fcoe_rx_list;
struct page *crc_eof_page;
int crc_eof_offset;
#define FCOE_CTLR_START_DELAY 2000 /* mS after first adv. to choose FCF */
#define FCOE_CTRL_SOL_TOV 2000 /* min. solicitation interval (mS) */
#define FCOE_CTLR_FCF_LIMIT 20 /* max. number of FCF entries */
/**
* enum fip_state - internal state of FCoE controller.
* @FIP_ST_DISABLED: controller has been disabled or not yet enabled.
* @FIP_ST_LINK_WAIT: the physical link is down or unusable.
* @FIP_ST_AUTO: determining whether to use FIP or non-FIP mode.
* @FIP_ST_NON_FIP: non-FIP mode selected.
* @FIP_ST_ENABLED: FIP mode selected.
*/
enum fip_state {
FIP_ST_DISABLED,
FIP_ST_LINK_WAIT,
FIP_ST_AUTO,
FIP_ST_NON_FIP,
FIP_ST_ENABLED,
};
/*
* the fcoe sw transport private data
/**
* struct fcoe_ctlr - FCoE Controller and FIP state.
* @state: internal FIP state for network link and FIP or non-FIP mode.
* @lp: &fc_lport: libfc local port.
* @sel_fcf: currently selected FCF, or NULL.
* @fcfs: list of discovered FCFs.
* @fcf_count: number of discovered FCF entries.
* @sol_time: time when a multicast solicitation was last sent.
* @sel_time: time after which to select an FCF.
* @port_ka_time: time of next port keep-alive.
* @ctlr_ka_time: time of next controller keep-alive.
* @timer: timer struct used for all delayed events.
* @link_work: &work_struct for doing FCF selection.
* @recv_work: &work_struct for receiving FIP frames.
* @fip_recv_list: list of received FIP frames.
* @user_mfs: configured maximum FC frame size, including FC header.
* @flogi_oxid: exchange ID of most recent fabric login.
* @flogi_count: number of FLOGI attempts in AUTO mode.
* @link: current link status for libfc.
* @last_link: last link state reported to libfc.
* @map_dest: use the FC_MAP mode for destination MAC addresses.
* @dest_addr: MAC address of the selected FC forwarder.
* @ctl_src_addr: the native MAC address of our local port.
* @data_src_addr: the assigned MAC address for the local port after FLOGI.
* @send: LLD-supplied function to handle sending of FIP Ethernet frames.
* @update_mac: LLD-supplied function to handle changes to MAC addresses.
* @lock: lock protecting this structure.
*
* This structure is used by all FCoE drivers. It contains information
* needed by all FCoE low-level drivers (LLDs) as well as internal state
* for FIP, and fields shared with the LLDS.
*/
struct fcoe_softc {
struct list_head list;
struct fcoe_ctlr {
enum fip_state state;
struct fc_lport *lp;
struct net_device *real_dev;
struct net_device *phys_dev; /* device with ethtool_ops */
struct packet_type fcoe_packet_type;
struct sk_buff_head fcoe_pending_queue;
u8 fcoe_pending_queue_active;
struct fcoe_fcf *sel_fcf;
struct list_head fcfs;
u16 fcf_count;
unsigned long sol_time;
unsigned long sel_time;
unsigned long port_ka_time;
unsigned long ctlr_ka_time;
struct timer_list timer;
struct work_struct link_work;
struct work_struct recv_work;
struct sk_buff_head fip_recv_list;
u16 user_mfs;
u16 flogi_oxid;
u8 flogi_count;
u8 link;
u8 last_link;
u8 map_dest;
u8 dest_addr[ETH_ALEN];
u8 ctl_src_addr[ETH_ALEN];
u8 data_src_addr[ETH_ALEN];
/*
* fcoe protocol address learning related stuff
*/
u16 flogi_oxid;
u8 flogi_progress;
u8 address_mode;
void (*send)(struct fcoe_ctlr *, struct sk_buff *);
void (*update_mac)(struct fcoe_ctlr *, u8 *old, u8 *new);
spinlock_t lock;
};
static inline struct net_device *fcoe_netdev(
const struct fc_lport *lp)
{
return ((struct fcoe_softc *)lport_priv(lp))->real_dev;
}
/*
* struct fcoe_fcf - Fibre-Channel Forwarder.
* @list: list linkage.
* @time: system time (jiffies) when an advertisement was last received.
* @switch_name: WWN of switch from advertisement.
* @fabric_name: WWN of fabric from advertisement.
* @fc_map: FC_MAP value from advertisement.
* @fcf_mac: Ethernet address of the FCF.
* @vfid: virtual fabric ID.
* @pri: seletion priority, smaller values are better.
* @flags: flags received from advertisement.
* @fka_period: keep-alive period, in jiffies.
*
* A Fibre-Channel Forwarder (FCF) is the entity on the Ethernet that
* passes FCoE frames on to an FC fabric. This structure represents
* one FCF from which advertisements have been received.
*
* When looking up an FCF, @switch_name, @fabric_name, @fc_map, @vfid, and
* @fcf_mac together form the lookup key.
*/
struct fcoe_fcf {
struct list_head list;
unsigned long time;
static inline struct fcoe_hdr *skb_fcoe_header(const struct sk_buff *skb)
{
return (struct fcoe_hdr *)skb_network_header(skb);
}
u64 switch_name;
u64 fabric_name;
u32 fc_map;
u16 vfid;
u8 fcf_mac[ETH_ALEN];
static inline int skb_fcoe_offset(const struct sk_buff *skb)
{
return skb_network_offset(skb);
}
u8 pri;
u16 flags;
u32 fka_period;
};
static inline struct fc_frame_header *skb_fc_header(const struct sk_buff *skb)
{
return (struct fc_frame_header *)skb_transport_header(skb);
}
static inline int skb_fc_offset(const struct sk_buff *skb)
{
return skb_transport_offset(skb);
}
static inline void skb_reset_fc_header(struct sk_buff *skb)
{
skb_reset_network_header(skb);
skb_set_transport_header(skb, skb_network_offset(skb) +
sizeof(struct fcoe_hdr));
}
static inline bool skb_fc_is_data(const struct sk_buff *skb)
{
return skb_fc_header(skb)->fh_r_ctl == FC_RCTL_DD_SOL_DATA;
}
static inline bool skb_fc_is_cmd(const struct sk_buff *skb)
{
return skb_fc_header(skb)->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD;
}
static inline bool skb_fc_has_exthdr(const struct sk_buff *skb)
{
return (skb_fc_header(skb)->fh_r_ctl == FC_RCTL_VFTH) ||
(skb_fc_header(skb)->fh_r_ctl == FC_RCTL_IFRH) ||
(skb_fc_header(skb)->fh_r_ctl == FC_RCTL_ENCH);
}
static inline bool skb_fc_is_roff(const struct sk_buff *skb)
{
return skb_fc_header(skb)->fh_f_ctl[2] & FC_FC_REL_OFF;
}
static inline u16 skb_fc_oxid(const struct sk_buff *skb)
{
return be16_to_cpu(skb_fc_header(skb)->fh_ox_id);
}
static inline u16 skb_fc_rxid(const struct sk_buff *skb)
{
return be16_to_cpu(skb_fc_header(skb)->fh_rx_id);
}
/* FIP API functions */
void fcoe_ctlr_init(struct fcoe_ctlr *);
void fcoe_ctlr_destroy(struct fcoe_ctlr *);
void fcoe_ctlr_link_up(struct fcoe_ctlr *);
int fcoe_ctlr_link_down(struct fcoe_ctlr *);
int fcoe_ctlr_els_send(struct fcoe_ctlr *, struct sk_buff *);
void fcoe_ctlr_recv(struct fcoe_ctlr *, struct sk_buff *);
int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_frame *fp, u8 *sa);
/* libfcoe funcs */
int fcoe_reset(struct Scsi_Host *shost);
u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
unsigned int scheme, unsigned int port);
u32 fcoe_fc_crc(struct fc_frame *fp);
int fcoe_xmit(struct fc_lport *, struct fc_frame *);
int fcoe_rcv(struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *);
int fcoe_percpu_receive_thread(void *arg);
void fcoe_clean_pending_queue(struct fc_lport *lp);
void fcoe_percpu_clean(struct fc_lport *lp);
void fcoe_watchdog(ulong vp);
int fcoe_link_ok(struct fc_lport *lp);
struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
int fcoe_hostlist_add(const struct fc_lport *);
int fcoe_hostlist_remove(const struct fc_lport *);
struct Scsi_Host *fcoe_host_alloc(struct scsi_host_template *, int);
u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int);
int fcoe_libfc_config(struct fc_lport *, struct libfc_function_template *);
/* fcoe sw hba */
int __init fcoe_sw_init(void);
int __exit fcoe_sw_exit(void);
#endif /* _LIBFCOE_H */