aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/ata/ahci.c26
-rw-r--r--drivers/ata/ata_piix.c29
-rw-r--r--drivers/ata/libata-acpi.c16
-rw-r--r--drivers/ata/libata-core.c69
-rw-r--r--drivers/ata/libata-eh.c14
-rw-r--r--drivers/ata/libata-scsi.c240
-rw-r--r--drivers/ata/libata-sff.c2
-rw-r--r--drivers/ata/pata_ns87415.c10
-rw-r--r--drivers/ata/sata_mv.c23
-rw-r--r--drivers/ata/sata_nv.c68
-rw-r--r--drivers/ata/sata_sx4.c4
-rw-r--r--drivers/fc4/Kconfig81
-rw-r--r--drivers/fc4/Makefile9
-rw-r--r--drivers/fc4/fc-al.h27
-rw-r--r--drivers/fc4/fc.c1146
-rw-r--r--drivers/fc4/fc.h230
-rw-r--r--drivers/fc4/fc_syms.c30
-rw-r--r--drivers/fc4/fcp.h94
-rw-r--r--drivers/fc4/fcp_impl.h164
-rw-r--r--drivers/fc4/soc.c764
-rw-r--r--drivers/fc4/soc.h301
-rw-r--r--drivers/fc4/socal.c904
-rw-r--r--drivers/fc4/socal.h314
-rw-r--r--drivers/net/Kconfig13
-rw-r--r--drivers/net/bonding/bond_3ad.c6
-rw-r--r--drivers/net/bonding/bond_3ad.h2
-rw-r--r--drivers/net/bonding/bond_alb.c110
-rw-r--r--drivers/net/bonding/bond_alb.h2
-rw-r--r--drivers/net/bonding/bond_main.c330
-rw-r--r--drivers/net/bonding/bond_sysfs.c79
-rw-r--r--drivers/net/bonding/bonding.h14
-rw-r--r--drivers/net/cpmac.c31
-rw-r--r--drivers/net/defxx.c2
-rw-r--r--drivers/net/eexpress.c2
-rw-r--r--drivers/net/mipsnet.c44
-rw-r--r--drivers/net/mv643xx_eth.c807
-rw-r--r--drivers/net/mv643xx_eth.h370
-rw-r--r--drivers/net/ni5010.c2
-rw-r--r--drivers/net/pasemi_mac.c2
-rw-r--r--drivers/net/r8169.c406
-rw-r--r--drivers/net/sky2.c4
-rw-r--r--drivers/pci/quirks.c2
-rw-r--r--drivers/scsi/Makefile2
-rw-r--r--drivers/scsi/aic7xxx/aic7770.c16
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h11
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c7
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c4
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c50
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c27
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h11
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c46
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c16
-rw-r--r--drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l3
-rw-r--r--drivers/scsi/aic7xxx_old.c2
-rw-r--r--drivers/scsi/fcal.c317
-rw-r--r--drivers/scsi/fcal.h27
-rw-r--r--drivers/scsi/gdth.c6
-rw-r--r--drivers/scsi/hosts.c6
-rw-r--r--drivers/scsi/hptiop.c5
-rw-r--r--drivers/scsi/initio.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c2
-rw-r--r--drivers/scsi/pluto.c349
-rw-r--r--drivers/scsi/pluto.h47
-rw-r--r--drivers/scsi/qla1280.c4
-rw-r--r--drivers/scsi/qla1280.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c9
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_devtbl.h7
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c50
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c30
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/scsi_error.c1
-rw-r--r--drivers/scsi/scsi_sysfs.c10
-rw-r--r--drivers/scsi/sym53c8xx_2/sym53c8xx.h1
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.c18
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c581
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h16
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c159
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h22
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.c2
-rw-r--r--drivers/watchdog/Kconfig13
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/ar7_wdt.c349
89 files changed, 2569 insertions, 6483 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 560496b4330..8cb37e3557d 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -34,7 +34,6 @@ obj-$(CONFIG_NUBUS) += nubus/
obj-$(CONFIG_ATM) += atm/
obj-y += macintosh/
obj-$(CONFIG_IDE) += ide/
-obj-$(CONFIG_FC4) += fc4/
obj-$(CONFIG_SCSI) += scsi/
obj-$(CONFIG_ATA) += ata/
obj-$(CONFIG_FUSION) += message/
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 47c80604052..95229e77bff 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -227,7 +227,7 @@ struct ahci_port_priv {
static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
-static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
static void ahci_irq_clear(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap);
@@ -729,7 +729,7 @@ static int ahci_stop_engine(struct ata_port *ap)
/* wait for engine to stop. This could be as long as 500 msec */
tmp = ata_wait_register(port_mmio + PORT_CMD,
- PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+ PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
if (tmp & PORT_CMD_LIST_ON)
return -EIO;
@@ -1564,9 +1564,9 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
if (!irq_stat)
return IRQ_NONE;
- spin_lock(&host->lock);
+ spin_lock(&host->lock);
- for (i = 0; i < host->n_ports; i++) {
+ for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
if (!(irq_stat & (1 << i)))
@@ -1829,9 +1829,9 @@ static int ahci_port_start(struct ata_port *ap)
pp->cmd_tbl_dma = mem_dma;
/*
- * Save off initial list of interrupts to be enabled.
- * This could be changed later
- */
+ * Save off initial list of interrupts to be enabled.
+ * This could be changed later
+ */
pp->intr_mask = DEF_PORT_IRQ;
ap->private_data = pp;
@@ -1918,12 +1918,12 @@ static void ahci_print_info(struct ata_host *host)
dev_printk(KERN_INFO, &pdev->dev,
"AHCI %02x%02x.%02x%02x "
"%u slots %u ports %s Gbps 0x%x impl %s mode\n"
- ,
+ ,
- (vers >> 24) & 0xff,
- (vers >> 16) & 0xff,
- (vers >> 8) & 0xff,
- vers & 0xff,
+ (vers >> 24) & 0xff,
+ (vers >> 16) & 0xff,
+ (vers >> 8) & 0xff,
+ vers & 0xff,
((cap >> 8) & 0x1f) + 1,
(cap & 0x1f) + 1,
@@ -1935,7 +1935,7 @@ static void ahci_print_info(struct ata_host *host)
"flags: "
"%s%s%s%s%s%s%s"
"%s%s%s%s%s%s%s\n"
- ,
+ ,
cap & (1 << 31) ? "64bit " : "",
cap & (1 << 30) ? "ncq " : "",
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 3c6f43e381f..a4b2cb29f46 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -157,12 +157,12 @@ struct piix_host_priv {
const int *map;
};
-static int piix_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent);
+static int piix_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent);
static void piix_pata_error_handler(struct ata_port *ap);
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
-static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
-static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev);
+static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);
+static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
static int ich_pata_cable_detect(struct ata_port *ap);
#ifdef CONFIG_PM
static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
@@ -650,9 +650,9 @@ static int ich_pata_cable_detect(struct ata_port *ap)
while (lap->device) {
if (lap->device == pdev->device &&
lap->subvendor == pdev->subsystem_vendor &&
- lap->subdevice == pdev->subsystem_device) {
+ lap->subdevice == pdev->subsystem_device)
return ATA_CBL_PATA40_SHORT;
- }
+
lap++;
}
@@ -699,7 +699,7 @@ static void piix_pata_error_handler(struct ata_port *ap)
* None (inherited from caller).
*/
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
+static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
unsigned int pio = adev->pio_mode - XFER_PIO_0;
struct pci_dev *dev = to_pci_dev(ap->host->dev);
@@ -786,7 +786,7 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
* None (inherited from caller).
*/
-static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, int isich)
+static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich)
{
struct pci_dev *dev = to_pci_dev(ap->host->dev);
u8 master_port = ap->port_no ? 0x42 : 0x40;
@@ -813,7 +813,7 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i
int u_clock, u_speed;
/*
- * UDMA is handled by a combination of clock switching and
+ * UDMA is handled by a combination of clock switching and
* selection of dividers
*
* Handy rule: Odd modes are UDMATIMx 01, even are 02
@@ -905,7 +905,7 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i
* None (inherited from caller).
*/
-static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
do_pata_set_dmamode(ap, adev, 0);
}
@@ -921,7 +921,7 @@ static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
* None (inherited from caller).
*/
-static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
do_pata_set_dmamode(ap, adev, 1);
}
@@ -1106,8 +1106,7 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
u16 cfg;
int no_piix_dma = 0;
- while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
- {
+ while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL) {
/* Look for 450NX PXB. Check for problem configurations
A PCI quirk checks bit 6 already */
pci_read_config_word(pdev, 0x41, &cfg);
@@ -1241,7 +1240,7 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
* Zero on success, or -ERRNO value.
*/
-static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
struct device *dev = &pdev->dev;
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 3f753358904..08a52dd45fb 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -26,7 +26,7 @@
#include <acpi/actypes.h>
#define NO_PORT_MULT 0xffff
-#define SATA_ADR(root,pmp) (((root) << 16) | (pmp))
+#define SATA_ADR(root, pmp) (((root) << 16) | (pmp))
#define REGS_PER_GTF 7
struct ata_acpi_gtf {
@@ -96,8 +96,8 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
}
}
-static void ata_acpi_handle_hotplug (struct ata_port *ap, struct kobject *kobj,
- u32 event)
+static void ata_acpi_handle_hotplug(struct ata_port *ap, struct kobject *kobj,
+ u32 event)
{
char event_string[12];
char *envp[] = { event_string, NULL };
@@ -114,7 +114,7 @@ static void ata_acpi_handle_hotplug (struct ata_port *ap, struct kobject *kobj,
}
if (kobj) {
- sprintf(event_string, "BAY_EVENT=%d", event);
+ sprintf(event_string, "BAY_EVENT=%d", event);
kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
}
}
@@ -127,14 +127,14 @@ static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
if (dev->sdev)
kobj = &dev->sdev->sdev_gendev.kobj;
- ata_acpi_handle_hotplug (dev->link->ap, kobj, event);
+ ata_acpi_handle_hotplug(dev->link->ap, kobj, event);
}
static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
{
struct ata_port *ap = data;
- ata_acpi_handle_hotplug (ap, &ap->dev->kobj, event);
+ ata_acpi_handle_hotplug(ap, &ap->dev->kobj, event);
}
/**
@@ -398,11 +398,11 @@ int ata_acpi_cbl_80wire(struct ata_port *ap)
{
struct ata_acpi_gtm gtm;
int valid = 0;
-
+
/* No _GTM data, no information */
if (ata_acpi_gtm(ap, &gtm) < 0)
return 0;
-
+
/* Split timing, DMA enabled */
if ((gtm.flags & 0x11) == 0x11 && gtm.drive[0].dma < 55)
valid |= 1;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 69092bce1ad..2d147b51c97 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -49,11 +49,11 @@
#include <linux/workqueue.h>
#include <linux/jiffies.h>
#include <linux/scatterlist.h>
+#include <linux/io.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
-#include <asm/io.h>
#include <asm/semaphore.h>
#include <asm/byteorder.h>
@@ -93,7 +93,7 @@ int libata_fua = 0;
module_param_named(fua, libata_fua, int, 0444);
MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
-static int ata_ignore_hpa = 0;
+static int ata_ignore_hpa;
module_param_named(ignore_hpa, ata_ignore_hpa, int, 0644);
MODULE_PARM_DESC(ignore_hpa, "Ignore HPA limit (0=keep BIOS limits, 1=ignore limits, using full disk)");
@@ -713,7 +713,7 @@ unsigned int ata_dev_classify(const struct ata_taskfile *tf)
}
if ((tf->lbam == 0x3c) && (tf->lbah == 0xc3)) {
- printk("ata: SEMB device ignored\n");
+ printk(KERN_INFO "ata: SEMB device ignored\n");
return ATA_DEV_SEMB_UNSUP; /* not yet */
}
@@ -939,7 +939,7 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
*max_sectors = ata_tf_to_lba48(&tf);
else
*max_sectors = ata_tf_to_lba(&tf);
- if (dev->horkage & ATA_HORKAGE_HPA_SIZE)
+ if (dev->horkage & ATA_HORKAGE_HPA_SIZE)
(*max_sectors)--;
return 0;
}
@@ -1151,7 +1151,7 @@ void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown)
* LOCKING:
* caller.
*/
-void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
+void ata_noop_dev_select(struct ata_port *ap, unsigned int device)
{
}
@@ -1171,7 +1171,7 @@ void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
* caller.
*/
-void ata_std_dev_select (struct ata_port *ap, unsigned int device)
+void ata_std_dev_select(struct ata_port *ap, unsigned int device)
{
u8 tmp;
@@ -1292,7 +1292,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
*/
u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
if (mode < 5) /* Valid PIO range */
- pio_mask = (2 << mode) - 1;
+ pio_mask = (2 << mode) - 1;
else
pio_mask = 1;
@@ -1693,7 +1693,7 @@ static u32 ata_pio_mask_no_iordy(const struct ata_device *adev)
* for pre-ATA4 drives.
*
* FIXME: ATA_CMD_ID_ATA is optional for early drives and right
- * now we abort if we hit that case.
+ * now we abort if we hit that case.
*
* LOCKING:
* Kernel thread context (may sleep)
@@ -1979,9 +1979,8 @@ int ata_dev_configure(struct ata_device *dev)
"supports DRM functions and may "
"not be fully accessable.\n");
snprintf(revbuf, 7, "CFA");
- }
- else
- snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
+ } else
+ snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
dev->n_sectors = ata_id_n_sectors(id);
@@ -2110,7 +2109,7 @@ int ata_dev_configure(struct ata_device *dev)
/* Let the user know. We don't want to disallow opens for
rescue purposes, or in case the vendor is just a blithering
idiot */
- if (print_info) {
+ if (print_info) {
ata_dev_printk(dev, KERN_WARNING,
"Drive reports diagnostics failure. This may indicate a drive\n");
ata_dev_printk(dev, KERN_WARNING,
@@ -2667,8 +2666,8 @@ static const struct ata_timing ata_timing[] = {
{ 0xFF }
};
-#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
-#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
+#define ENOUGH(v, unit) (((v)-1)/(unit)+1)
+#define EZ(v, unit) ((v)?ENOUGH(v, unit):0)
static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
{
@@ -2695,7 +2694,7 @@ void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
if (what & ATA_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
}
-static const struct ata_timing* ata_timing_find_mode(unsigned short speed)
+static const struct ata_timing *ata_timing_find_mode(unsigned short speed)
{
const struct ata_timing *t;
@@ -2727,10 +2726,10 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
memset(&p, 0, sizeof(p));
- if(speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
+ if (speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
- } else if(speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
+ } else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
}
ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
@@ -2876,14 +2875,17 @@ static int ata_dev_set_mode(struct ata_device *dev)
dev->flags |= ATA_DFLAG_PIO;
err_mask = ata_dev_set_xfermode(dev);
+
/* Old CFA may refuse this command, which is just fine */
if (dev->xfer_shift == ATA_SHIFT_PIO && ata_id_is_cfa(dev->id))
- err_mask &= ~AC_ERR_DEV;
+ err_mask &= ~AC_ERR_DEV;
+
/* Some very old devices and some bad newer ones fail any kind of
SET_XFERMODE request but support PIO0-2 timings and no IORDY */
if (dev->xfer_shift == ATA_SHIFT_PIO && !ata_id_has_iordy(dev->id) &&
dev->pio_mode <= XFER_PIO_2)
err_mask &= ~AC_ERR_DEV;
+
if (err_mask) {
ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
"(err_mask=0x%x)\n", err_mask);
@@ -3265,7 +3267,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
* the bus shows 0xFF because the odd clown forgets the D7
* pulldown resistor.
*/
- if (ata_check_status(ap) == 0xFF)
+ if (ata_chk_status(ap) == 0xFF)
return -ENODEV;
return ata_bus_post_reset(ap, devmask, deadline);
@@ -3943,7 +3945,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "SAMSUNG CD-ROM SC", NULL, ATA_HORKAGE_NODMA },
{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA },
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
- { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
+ { "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA },
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
{ "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */
{ "IOMEGA ZIP 250 ATAPI Floppy",
@@ -3959,7 +3961,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices where NCQ should be avoided */
/* NCQ is slow */
- { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ },
+ { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ },
/* http://thread.gmane.org/gmane.linux.ide/14907 */
{ "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ },
/* NCQ is broken */
@@ -3979,6 +3981,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "HTS541612J9SA00", "SBDIC7JP", ATA_HORKAGE_NONCQ, },
{ "HDT722516DLA380", "V43OA96A", ATA_HORKAGE_NONCQ, },
{ "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, },
+ { "Hitachi HTS542525K9SA00", "BBFOC31P", ATA_HORKAGE_NONCQ, },
{ "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, },
{ "WDC WD3200AAJS-00RYA0", "12.01B01", ATA_HORKAGE_NONCQ, },
{ "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, },
@@ -4106,7 +4109,7 @@ static void ata_dev_xfermask(struct ata_device *dev)
}
if ((host->flags & ATA_HOST_SIMPLEX) &&
- host->simplex_claimed && host->simplex_claimed != ap) {
+ host->simplex_claimed && host->simplex_claimed != ap) {
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by "
"other device, disabling DMA\n");
@@ -4128,11 +4131,11 @@ static void ata_dev_xfermask(struct ata_device *dev)
*/
if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
/* UDMA/44 or higher would be available */
- if((ap->cbl == ATA_CBL_PATA40) ||
- (ata_drive_40wire(dev->id) &&
- (ap->cbl == ATA_CBL_PATA_UNK ||
- ap->cbl == ATA_CBL_PATA80))) {
- ata_dev_printk(dev, KERN_WARNING,
+ if ((ap->cbl == ATA_CBL_PATA40) ||
+ (ata_drive_40wire(dev->id) &&
+ (ap->cbl == ATA_CBL_PATA_UNK ||
+ ap->cbl == ATA_CBL_PATA80))) {
+ ata_dev_printk(dev, KERN_WARNING,
"limited to UDMA/33 due to 40-wire cable\n");
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
}
@@ -4395,7 +4398,7 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
u32 addr, offset;
u32 sg_len, len, blen;
- /* determine if physical DMA addr spans 64K boundary.
+ /* determine if physical DMA addr spans 64K boundary.
* Note h/w doesn't support 64-bit, so we unconditionally
* truncate dma_addr_t to u32.
*/
@@ -4980,7 +4983,7 @@ next_sg:
"%u bytes trailing data\n", bytes);
for (i = 0; i < words; i++)
- ap->ops->data_xfer(qc->dev, (unsigned char*)pad_buf, 2, do_write);
+ ap->ops->data_xfer(qc->dev, (unsigned char *)pad_buf, 2, do_write);
ap->hsm_task_state = HSM_ST_LAST;
return;
@@ -5908,8 +5911,8 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
* One if interrupt was handled, zero if not (shared irq).
*/
-inline unsigned int ata_host_intr (struct ata_port *ap,
- struct ata_queued_cmd *qc)
+inline unsigned int ata_host_intr(struct ata_port *ap,
+ struct ata_queued_cmd *qc)
{
struct ata_eh_info *ehi = &ap->link.eh_info;
u8 status, host_stat = 0;
@@ -6009,7 +6012,7 @@ idle_irq:
* IRQ_NONE or IRQ_HANDLED.
*/
-irqreturn_t ata_interrupt (int irq, void *dev_instance)
+irqreturn_t ata_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
unsigned int i;
@@ -6212,7 +6215,7 @@ int ata_flush_cache(struct ata_device *dev)
/* This is wrong. On a failed flush we get back the LBA of the lost
sector and we should (assuming it wasn't aborted as unknown) issue
- a further flush command to continue the writeback until it
+ a further flush command to continue the writeback until it
does not error */
err_mask = ata_do_simple_cmd(dev, cmd);
if (err_mask) {
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 2eaa39fc65d..93e2b545b43 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1197,7 +1197,7 @@ void ata_eh_done(struct ata_link *link, struct ata_device *dev,
* RETURNS:
* Descriptive string for @err_mask
*/
-static const char * ata_err_string(unsigned int err_mask)
+static const char *ata_err_string(unsigned int err_mask)
{
if (err_mask & AC_ERR_HOST_BUS)
return "host bus error";
@@ -1934,7 +1934,7 @@ static void ata_eh_link_report(struct ata_link *link)
ehc->i.serror & SERR_LINK_SEQ_ERR ? "LinkSeq " : "",
ehc->i.serror & SERR_TRANS_ST_ERROR ? "TrStaTrns " : "",
ehc->i.serror & SERR_UNRECOG_FIS ? "UnrecFIS " : "",
- ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : "" );
+ ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : "");
for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
static const char *dma_str[] = {
@@ -1969,17 +1969,17 @@ static void ata_eh_link_report(struct ata_link *link)
qc->err_mask & AC_ERR_NCQ ? " <F>" : "");
if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
- ATA_ERR) ) {
+ ATA_ERR)) {
if (res->command & ATA_BUSY)
ata_dev_printk(qc->dev, KERN_ERR,
- "status: { Busy }\n" );
+ "status: { Busy }\n");
else
ata_dev_printk(qc->dev, KERN_ERR,
"status: { %s%s%s%s}\n",
res->command & ATA_DRDY ? "DRDY " : "",
res->command & ATA_DF ? "DF " : "",
res->command & ATA_DRQ ? "DRQ " : "",
- res->command & ATA_ERR ? "ERR " : "" );
+ res->command & ATA_ERR ? "ERR " : "");
}
if (cmd->command != ATA_CMD_PACKET &&
@@ -1990,7 +1990,7 @@ static void ata_eh_link_report(struct ata_link *link)
res->feature & ATA_ICRC ? "ICRC " : "",
res->feature & ATA_UNC ? "UNC " : "",
res->feature & ATA_IDNF ? "IDNF " : "",
- res->feature & ATA_ABORTED ? "ABRT " : "" );
+ res->feature & ATA_ABORTED ? "ABRT " : "");
}
}
@@ -2611,7 +2611,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ehc->i.flags = 0;
continue;
- dev_fail:
+dev_fail:
nr_failed_devs++;
if (ata_eh_handle_dev_fail(dev, rc))
nr_disabled_devs++;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 5b758b9ad0b..f5d5420a1ba 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -45,7 +45,7 @@
#include <scsi/scsi_transport.h>
#include <linux/libata.h>
#include <linux/hdreg.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include "libata.h"
@@ -53,9 +53,9 @@
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
-static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
+static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
-static struct ata_device * ata_scsi_find_dev(struct ata_port *ap,
+static struct ata_device *ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun);
@@ -228,7 +228,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
scsi_cmd[1] = (4 << 1); /* PIO Data-in */
scsi_cmd[2] = 0x0e; /* no off.line or cc, read from dev,
- block count in sector count field */
+ block count in sector count field */
data_dir = DMA_FROM_DEVICE;
} else {
scsi_cmd[1] = (3 << 1); /* Non-data */
@@ -252,7 +252,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
/* Good values for timeout and retries? Values below
from scsi_ioctl_send_command() for default case... */
cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,
- sensebuf, (10*HZ), 5, 0);
+ sensebuf, (10*HZ), 5, 0);
if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
u8 *desc = sensebuf + 8;
@@ -263,18 +263,18 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
if (cmd_result & SAM_STAT_CHECK_CONDITION) {
struct scsi_sense_hdr sshdr;
scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
- &sshdr);
- if (sshdr.sense_key==0 &&
- sshdr.asc==0 && sshdr.ascq==0)
+ &sshdr);
+ if (sshdr.sense_key == 0 &&
+ sshdr.asc == 0 && sshdr.ascq == 0)
cmd_result &= ~SAM_STAT_CHECK_CONDITION;
}
/* Send userspace a few ATA registers (same as drivers/ide) */
- if (sensebuf[0] == 0x72 && /* format is "descriptor" */
- desc[0] == 0x09 ) { /* code is "ATA Descriptor" */
- args[0] = desc[13]; /* status */
- args[1] = desc[3]; /* error */
- args[2] = desc[5]; /* sector count (0:7) */
+ if (sensebuf[0] == 0x72 && /* format is "descriptor" */
+ desc[0] == 0x09) { /* code is "ATA Descriptor" */
+ args[0] = desc[13]; /* status */
+ args[1] = desc[3]; /* error */
+ args[2] = desc[5]; /* sector count (0:7) */
if (copy_to_user(arg, args, sizeof(args)))
rc = -EFAULT;
}
@@ -350,8 +350,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
struct scsi_sense_hdr sshdr;
scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
&sshdr);
- if (sshdr.sense_key==0 &&
- sshdr.asc==0 && sshdr.ascq==0)
+ if (sshdr.sense_key == 0 &&
+ sshdr.asc == 0 && sshdr.ascq == 0)
cmd_result &= ~SAM_STAT_CHECK_CONDITION;
}
@@ -975,7 +975,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
if ((qc->dev->flags & ATA_DFLAG_SPUNDOWN) &&
(system_state == SYSTEM_HALT ||
system_state == SYSTEM_POWER_OFF)) {
- static unsigned long warned = 0;
+ static unsigned long warned;
if (!test_and_set_bit(0, &warned)) {
ata_dev_printk(qc->dev, KERN_WARNING,
@@ -1364,7 +1364,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
struct ata_eh_info *ehi = &qc->dev->link->eh_info;
struct scsi_cmnd *cmd = qc->scsicmd;
u8 *cdb = cmd->cmnd;
- int need_sense = (qc->err_mask != 0);
+ int need_sense = (qc->err_mask != 0);
/* We snoop the SET_FEATURES - Write Cache ON/OFF command, and
* schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
@@ -1396,7 +1396,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* was no error, SK, ASC and ASCQ will all be zero.
*/
if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
- ((cdb[2] & 0x20) || need_sense)) {
+ ((cdb[2] & 0x20) || need_sense)) {
ata_gen_passthru_sense(qc);
} else {
if (!need_sense) {
@@ -1500,7 +1500,7 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
return 0;
early_finish:
- ata_qc_free(qc);
+ ata_qc_free(qc);
qc->scsidone(cmd);
DPRINTK("EXIT - early finish (good or error)\n");
return 0;
@@ -1590,8 +1590,8 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
*/
void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
- unsigned int (*actor) (struct ata_scsi_args *args,
- u8 *rbuf, unsigned int buflen))
+ unsigned int (*actor) (struct ata_scsi_args *args,
+ u8 *rbuf, unsigned int buflen))
{
u8 *rbuf;
unsigned int buflen, rc;
@@ -2140,7 +2140,7 @@ saving_not_supp:
* None.
*/
unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
- unsigned int buflen)
+ unsigned int buflen)
{
u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
@@ -2464,7 +2464,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
return 0;
}
-static struct ata_device * ata_find_dev(struct ata_port *ap, int devno)
+static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
{
if (ap->nr_pmp_links == 0) {
if (likely(devno < ata_link_max_devices(&ap->link)))
@@ -2477,8 +2477,8 @@ static struct ata_device * ata_find_dev(struct ata_port *ap, int devno)
return NULL;
}
-static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
- const struct scsi_device *scsidev)
+static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
+ const struct scsi_device *scsidev)
{
int devno;
@@ -2564,27 +2564,27 @@ static u8
ata_scsi_map_proto(u8 byte1)
{
switch((byte1 & 0x1e) >> 1) {
- case 3: /* Non-data */
- return ATA_PROT_NODATA;
-
- case 6: /* DMA */
- case 10: /* UDMA Data-in */
- case 11: /* UDMA Data-Out */
- return ATA_PROT_DMA;
-
- case 4: /* PIO Data-in */
- case 5: /* PIO Data-out */
- return ATA_PROT_PIO;
-
- case 0: /* Hard Reset */
- case 1: /* SRST */
- case 8: /* Device Diagnostic */
- case 9: /* Device Reset */
- case 7: /* DMA Queued */
- case 12: /* FPDMA */
- case 15: /* Return Response Info */
- default: /* Reserved */
- break;
+ case 3: /* Non-data */
+ return ATA_PROT_NODATA;
+
+ case 6: /* DMA */
+ case 10: /* UDMA Data-in */
+ case 11: /* UDMA Data-Out */
+ return ATA_PROT_DMA;
+
+ case 4: /* PIO Data-in */
+ case 5: /* PIO Data-out */
+ return ATA_PROT_PIO;
+
+ case 0: /* Hard Reset */
+ case 1: /* SRST */
+ case 8: /* Device Diagnostic */
+ case 9: /* Device Reset */
+ case 7: /* DMA Queued */
+ case 12: /* FPDMA */
+ case 15: /* Return Response Info */
+ default: /* Reserved */
+ break;
}
return ATA_PROT_UNKNOWN;
@@ -2919,94 +2919,94 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
args.done = done;
switch(scsicmd[0]) {
- /* TODO: worth improving? */
- case FORMAT_UNIT:
+ /* TODO: worth improving? */
+ case FORMAT_UNIT:
+ ata_scsi_invalid_field(cmd, done);
+ break;
+
+ case INQUIRY:
+ if (scsicmd[1] & 2) /* is CmdDt set? */
ata_scsi_invalid_field(cmd, done);
+ else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
+ else switch (scsicmd[2]) {
+ case 0x00:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
break;
-
- case INQUIRY:
- if (scsicmd[1] & 2) /* is CmdDt set? */
- ata_scsi_invalid_field(cmd, done);
- else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
- else switch (scsicmd[2]) {
- case 0x00:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
- break;
- case 0x80:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
- break;
- case 0x83:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
- break;
- case 0x89:
- ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
- break;
- default:
- ata_scsi_invalid_field(cmd, done);
- break;
- }
+ case 0x80:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
break;
-
- case MODE_SENSE:
- case MODE_SENSE_10:
- ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
+ case 0x83:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
break;
-
- case MODE_SELECT: /* unconditionally return */
- case MODE_SELECT_10: /* bad-field-in-cdb */
+ case 0x89:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
+ break;
+ default:
ata_scsi_invalid_field(cmd, done);
break;
+ }
+ break;
+
+ case MODE_SENSE:
+ case MODE_SENSE_10:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
+ break;
- case READ_CAPACITY:
+ case MODE_SELECT: /* unconditionally return */
+ case MODE_SELECT_10: /* bad-field-in-cdb */
+ ata_scsi_invalid_field(cmd, done);
+ break;
+
+ case READ_CAPACITY:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
+ break;
+
+ case SERVICE_ACTION_IN:
+ if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
- break;
+ else
+ ata_scsi_invalid_field(cmd, done);
+ break;
- case SERVICE_ACTION_IN:
- if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
- ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
- else
- ata_scsi_invalid_field(cmd, done);
- break;
+ case REPORT_LUNS:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
+ break;
- case REPORT_LUNS:
- ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
- break;
+ case REQUEST_SENSE:
+ ata_scsi_set_sense(cmd, 0, 0, 0);
+ cmd->result = (DRIVER_SENSE << 24);
+ done(cmd);
+ break;
- case REQUEST_SENSE:
- ata_scsi_set_sense(cmd, 0, 0, 0);
- cmd->result = (DRIVER_SENSE << 24);
- done(cmd);
- break;
+ /* if we reach this, then writeback caching is disabled,
+ * turning this into a no-op.
+ */
+ case SYNCHRONIZE_CACHE:
+ /* fall through */
+
+ /* no-op's, complete with success */
+ case REZERO_UNIT:
+ case SEEK_6:
+ case SEEK_10:
+ case TEST_UNIT_READY:
+ ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
+ break;
- /* if we reach this, then writeback caching is disabled,
- * turning this into a no-op.
- */
- case SYNCHRONIZE_CACHE:
- /* fall through */
-
- /* no-op's, complete with success */
- case REZERO_UNIT:
- case SEEK_6:
- case SEEK_10:
- case TEST_UNIT_READY:
+ case SEND_DIAGNOSTIC:
+ tmp8 = scsicmd[1] & ~(1 << 3);
+ if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4]))
ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
- break;
-
- case SEND_DIAGNOSTIC:
- tmp8 = scsicmd[1] & ~(1 << 3);
- if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4]))
- ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
- else
- ata_scsi_invalid_field(cmd, done);
- break;
+ else
+ ata_scsi_invalid_field(cmd, done);
+ break;
- /* all other commands */
- default:
- ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
- /* "Invalid command operation code" */
- done(cmd);
- break;
+ /* all other commands */
+ default:
+ ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
+ /* "Invalid command operation code" */
+ done(cmd);
+ break;
}
}
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 8227c45109e..48acc09dab9 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -248,7 +248,7 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
* LOCKING:
* spin_lock_irqsave(host lock)
*/
-void ata_bmdma_start (struct ata_queued_cmd *qc)
+void ata_bmdma_start(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
u8 dmactl;
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c
index bb97ef583f9..b9a17eb100d 100644
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -17,7 +17,7 @@
* TODO:
* Test PARISC SuperIO
* Get someone to test on SPARC
- * Implement lazy pio/dma switching for better performance
+ * Implement lazy pio/dma switching for better performance
* 8bit shared timing.
* See if we need to kill the FIFO for ATAPI
*/
@@ -60,10 +60,10 @@ static void ns87415_set_mode(struct ata_port *ap, struct ata_device *adev, u8 mo
u16 clocking;
u8 iordy;
u8 status;
-
+
/* Timing register format is 17 - low nybble read timing with
the high nybble being 16 - x for recovery time in PCI clocks */
-
+
ata_timing_compute(adev, adev->pio_mode, &t, T, 0);
clocking = 17 - FIT(t.active, 2, 17);
@@ -71,7 +71,7 @@ static void ns87415_set_mode(struct ata_port *ap, struct ata_device *adev, u8 mo
/* Use the same timing for read and write bytes */
clocking |= (clocking << 8);
pci_write_config_word(dev, timing, clocking);
-
+
/* Set the IORDY enable versus DMA enable on or off properly */
pci_read_config_byte(dev, 0x42, &iordy);
iordy &= ~(1 << (4 + unit));
@@ -185,7 +185,7 @@ static void ns87415_bmdma_irq_clear(struct ata_port *ap)
if (!mmio)
return;
- iowrite8((ioread8(mmio + ATA_DMA_CMD) | ATA_DMA_INTR | ATA_DMA_ERR),
+ iowrite8((ioread8(mmio + ATA_DMA_CMD) | ATA_DMA_INTR | ATA_DMA_ERR),
mmio + ATA_DMA_CMD);
}
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 7f1b13e89cf..b39648f0914 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -845,7 +845,7 @@ static int __mv_stop_dma(struct ata_port *ap)
pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
} else {
WARN_ON(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
- }
+ }
/* now properly wait for the eDMA to stop */
for (i = 1000; i > 0; i--) {
@@ -883,7 +883,7 @@ static void mv_dump_mem(void __iomem *start, unsigned bytes)
for (b = 0; b < bytes; ) {
DPRINTK("%p: ", start + b);
for (w = 0; b < bytes && w < 4; w++) {
- printk("%08x ",readl(start + b));
+ printk("%08x ", readl(start + b));
b += sizeof(u32);
}
printk("\n");
@@ -899,8 +899,8 @@ static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
for (b = 0; b < bytes; ) {
DPRINTK("%02x: ", b);
for (w = 0; b < bytes && w < 4; w++) {
- (void) pci_read_config_dword(pdev,b,&dw);
- printk("%08x ",dw);
+ (void) pci_read_config_dword(pdev, b, &dw);
+ printk("%08x ", dw);
b += sizeof(u32);
}
printk("\n");
@@ -944,9 +944,9 @@ static void mv_dump_all_regs(void __iomem *mmio_base, int port,
}
for (p = start_port; p < start_port + num_ports; p++) {
port_base = mv_port_base(mmio_base, p);
- DPRINTK("EDMA regs (port %i):\n",p);
+ DPRINTK("EDMA regs (port %i):\n", p);
mv_dump_mem(port_base, 0x54);
- DPRINTK("SATA regs (port %i):\n",p);
+ DPRINTK("SATA regs (port %i):\n", p);
mv_dump_mem(port_base+0x300, 0x60);
}
#endif
@@ -1184,7 +1184,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
u16 flags = 0;
unsigned in_index;
- if (qc->tf.protocol != ATA_PROT_DMA)
+ if (qc->tf.protocol != ATA_PROT_DMA)
return;
/* Fill in command request block
@@ -1276,7 +1276,7 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
unsigned in_index;
u32 flags = 0;
- if (qc->tf.protocol != ATA_PROT_DMA)
+ if (qc->tf.protocol != ATA_PROT_DMA)
return;
/* Fill in Gen IIE command request block
@@ -1606,7 +1606,7 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
- hc,relevant,hc_irq_cause);
+ hc, relevant, hc_irq_cause);
for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
struct ata_port *ap = host->ports[port];
@@ -1983,9 +1983,8 @@ static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
for (i = 0; i < 1000; i++) {
udelay(1);
t = readl(reg);
- if (PCI_MASTER_EMPTY & t) {
+ if (PCI_MASTER_EMPTY & t)
break;
- }
}
if (!(PCI_MASTER_EMPTY & t)) {
printk(KERN_ERR DRV_NAME ": PCI master won't flush\n");
@@ -2668,7 +2667,7 @@ static void mv_print_info(struct ata_host *host)
*/
static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- static int printed_version = 0;
+ static int printed_version;
unsigned int board_idx = (unsigned int)ent->driver_data;
const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };
struct ata_host *host;
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 240a8920d0b..2e0279fdd7a 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -163,7 +163,7 @@ enum {
NV_ADMA_STAT_STOPPED = (1 << 10),
NV_ADMA_STAT_DONE = (1 << 12),
NV_ADMA_STAT_ERR = NV_ADMA_STAT_CPBERR |
- NV_ADMA_STAT_TIMEOUT,
+ NV_ADMA_STAT_TIMEOUT,
/* port flags */
NV_ADMA_PORT_REGISTER_MODE = (1 << 0),
@@ -228,7 +228,7 @@ struct nv_adma_cpb {
u8 reserved1; /* 1 */
u8 ctl_flags; /* 2 */
/* len is length of taskfile in 64 bit words */
- u8 len; /* 3 */
+ u8 len; /* 3 */
u8 tag; /* 4 */
u8 next_cpb_idx; /* 5 */
__le16 reserved2; /* 6-7 */
@@ -244,9 +244,9 @@ struct nv_adma_port_priv {
dma_addr_t cpb_dma;
struct nv_adma_prd *aprd;
dma_addr_t aprd_dma;
- void __iomem * ctl_block;
- void __iomem * gen_block;
- void __iomem * notifier_clear_block;
+ void __iomem *ctl_block;
+ void __iomem *gen_block;
+ void __iomem *notifier_clear_block;
u8 flags;
int last_issue_ncq;
};
@@ -293,7 +293,7 @@ struct nv_swncq_port_priv {
#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))
-static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
#ifdef CONFIG_PM
static int nv_pci_device_resume(struct pci_dev *pdev);
#endif
@@ -301,8 +301,8 @@ static void nv_ck804_host_stop(struct ata_host *host);
static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
-static int nv_scr_read (struct ata_port *ap, unsigned int sc_reg, u32 *val);
-static int nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int nv_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
+static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static void nv_nf2_freeze(struct ata_port *ap);
static void nv_nf2_thaw(struct ata_port *ap);
@@ -653,12 +653,12 @@ static void nv_adma_register_mode(struct ata_port *ap)
return;
status = readw(mmio + NV_ADMA_STAT);
- while(!(status & NV_ADMA_STAT_IDLE) && count < 20) {
+ while (!(status & NV_ADMA_STAT_IDLE) && count < 20) {
ndelay(50);
status = readw(mmio + NV_ADMA_STAT);
count++;
}
- if(count == 20)
+ if (count == 20)
ata_port_printk(ap, KERN_WARNING,
"timeout waiting for ADMA IDLE, stat=0x%hx\n",
status);
@@ -668,12 +668,12 @@ static void nv_adma_register_mode(struct ata_port *ap)
count = 0;
status = readw(mmio + NV_ADMA_STAT);
- while(!(status & NV_ADMA_STAT_LEGACY) && count < 20) {
+ while (!(status & NV_ADMA_STAT_LEGACY) && count < 20) {
ndelay(50);
status = readw(mmio + NV_ADMA_STAT);
count++;
}
- if(count == 20)
+ if (count == 20)
ata_port_printk(ap, KERN_WARNING,
"timeout waiting for ADMA LEGACY, stat=0x%hx\n",
status);
@@ -697,13 +697,13 @@ static void nv_adma_mode(struct ata_port *ap)
writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
status = readw(mmio + NV_ADMA_STAT);
- while(((status & NV_ADMA_STAT_LEGACY) ||
+ while (((status & NV_ADMA_STAT_LEGACY) ||
!(status & NV_ADMA_STAT_IDLE)) && count < 20) {
ndelay(50);
status = readw(mmio + NV_ADMA_STAT);
count++;
}
- if(count == 20)
+ if (count == 20)
ata_port_printk(ap, KERN_WARNING,
"timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",
status);
@@ -747,8 +747,7 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
on the port. */
adma_enable = 0;
nv_adma_register_mode(ap);
- }
- else {
+ } else {
bounce_limit = *ap->dev->dma_mask;
segment_boundary = NV_ADMA_DMA_BOUNDARY;
sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN;
@@ -757,23 +756,22 @@ static int nv_adma_slave_config(struct scsi_device *sdev)
pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &current_reg);
- if(ap->port_no == 1)
+ if (ap->port_no == 1)
config_mask = NV_MCP_SATA_CFG_20_PORT1_EN |
NV_MCP_SATA_CFG_20_PORT1_PWB_EN;
else
config_mask = NV_MCP_SATA_CFG_20_PORT0_EN |
NV_MCP_SATA_CFG_20_PORT0_PWB_EN;
- if(adma_enable) {
+ if (adma_enable) {
new_reg = current_reg | config_mask;
pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE;
- }
- else {
+ } else {
new_reg = current_reg & ~config_mask;
pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE;
}
- if(current_reg != new_reg)
+ if (current_reg != new_reg)
pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg);
blk_queue_bounce_limit(sdev->request_queue, bounce_limit);
@@ -807,7 +805,7 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
{
unsigned int idx = 0;
- if(tf->flags & ATA_TFLAG_ISADDR) {
+ if (tf->flags & ATA_TFLAG_ISADDR) {
if (tf->flags & ATA_TFLAG_LBA48) {
cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature | WNB);
cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect);
@@ -824,12 +822,12 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah);
}
- if(tf->flags & ATA_TFLAG_DEVICE)
+ if (tf->flags & ATA_TFLAG_DEVICE)
cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device);
cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND);
- while(idx < 12)
+ while (idx < 12)
cpb[idx++] = cpu_to_le16(IGN);
return idx;
@@ -850,7 +848,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
int freeze = 0;
ata_ehi_clear_desc(ehi);
- __ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x: ", flags );
+ __ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x: ", flags);
if (flags & NV_CPB_RESP_ATA_ERR) {
ata_ehi_push_desc(ehi, "ATA error");
ehi->err_mask |= AC_ERR_DEV;
@@ -879,7 +877,7 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
VPRINTK("CPB flags done, flags=0x%x\n", flags);
if (likely(qc)) {
- DPRINTK("Completing qc from tag %d\n",cpb_num);
+ DPRINTK("Completing qc from tag %d\n", cpb_num);
ata_qc_complete(qc);
} else {
struct ata_eh_info *ehi = &ap->link.eh_info;
@@ -952,7 +950,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
>> (NV_INT_PORT_SHIFT * i);
- if(ata_tag_valid(ap->link.active_tag))
+ if (ata_tag_valid(ap->link.active_tag))
/** NV_INT_DEV indication seems unreliable at times
at least in ADMA mode. Force it on always when a
command is active, to prevent losing interrupts. */
@@ -966,7 +964,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
- if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier &&
+ if (!NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier &&
!notifier_error)
/* Nothing to do */
continue;
@@ -990,7 +988,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
struct ata_eh_info *ehi = &ap->link.eh_info;
ata_ehi_clear_desc(ehi);
- __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status );
+ __ata_ehi_push_desc(ehi, "ADMA status 0x%08x: ", status);
if (status & NV_ADMA_STAT_TIMEOUT) {
ehi->err_mask |= AC_ERR_SYSTEM;
ata_ehi_push_desc(ehi, "timeout");
@@ -1056,14 +1054,14 @@ static void nv_adma_freeze(struct ata_port *ap)
return;
/* clear any outstanding CK804 notifications */
- writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
+ writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
/* Disable interrupt */
tmp = readw(mmio + NV_ADMA_CTL);
- writew( tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+ writew(tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL ); /* flush posted write */
}
static void nv_adma_thaw(struct ata_port *ap)
@@ -1079,9 +1077,9 @@ static void nv_adma_thaw(struct ata_port *ap)
/* Enable interrupt */
tmp = readw(mmio + NV_ADMA_CTL);
- writew( tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
+ writew(tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN),
mmio + NV_ADMA_CTL);
- readw( mmio + NV_ADMA_CTL ); /* flush posted write */
+ readw(mmio + NV_ADMA_CTL ); /* flush posted write */
}
static void nv_adma_irq_clear(struct ata_port *ap)
@@ -1096,7 +1094,7 @@ static void nv_adma_irq_clear(struct ata_port *ap)
}
/* clear any outstanding CK804 notifications */
- writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
+ writeb(NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT),
ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
/* clear ADMA status */
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 9f9f7b30654..b6026bceccd 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -62,13 +62,13 @@
submit ATA packet to hardware
hardware executes ATA WRITE command, w/ data in DIMM
hardware raises interrupt
-
+
and each READ looks like this:
submit ATA packet to hardware
hardware executes ATA READ command, w/ data in DIMM
hardware raises interrupt
-
+
submit HDMA packet to hardware
hardware copies data from DIMM to system memory
hardware raises interrupt
diff --git a/drivers/fc4/Kconfig b/drivers/fc4/Kconfig
deleted file mode 100644
index 345dbe6f10d..00000000000
--- a/drivers/fc4/Kconfig
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# FC4 device configuration
-#
-
-menu "Fibre Channel support"
-
-config FC4
- tristate "Fibre Channel and FC4 SCSI support"
- ---help---
- Fibre Channel is a high speed serial protocol mainly used to
- connect large storage devices to the computer; it is compatible with
- and intended to replace SCSI.
-
- This is an experimental support for storage arrays connected to your
- computer using optical fibre cables and the "X3.269-199X Fibre
- Channel Protocol for SCSI" specification. If you want to use this,
- you need to say Y here and to "SCSI support" as well as to the
- drivers for the storage array itself and for the interface adapter
- such as SOC or SOC+. This subsystem could even serve for IP
- networking, with some code extensions.
-
- If unsure, say N.
-
-comment "FC4 drivers"
- depends on FC4
-
-config FC4_SOC
- tristate "Sun SOC/Sbus"
- depends on FC4!=n && SPARC
- help
- Serial Optical Channel is an interface card with one or two Fibre
- Optic ports, each of which can be connected to a disk array. Note
- that if you have older firmware in the card, you'll need the
- microcode from the Solaris driver to make it work.
-
- To compile this support as a module, choose M here: the module will
- be called soc.
-
-config FC4_SOCAL
- tristate "Sun SOC+ (aka SOCAL)"
- depends on FC4!=n && SPARC
- ---help---
- Serial Optical Channel Plus is an interface card with up to two
- Fibre Optic ports. This card supports FC Arbitrated Loop (usually
- A5000 or internal FC disks in E[3-6]000 machines through the
- Interface Board). You'll probably need the microcode from the
- Solaris driver to make it work.
-
- To compile this support as a module, choose M here: the module will
- be called socal.
-
-comment "FC4 targets"
- depends on FC4
-
-config SCSI_PLUTO
- tristate "SparcSTORAGE Array 100 and 200 series"
- depends on FC4!=n && SCSI
- help
- If you never bought a disk array made by Sun, go with N.
-
- To compile this support as a module, choose M here: the module will
- be called pluto.
-
-config SCSI_FCAL
- tristate "Sun Enterprise Network Array (A5000 and EX500)" if SPARC
- depends on FC4!=n && SCSI
- help
- This driver drives FC-AL disks connected through a Fibre Channel
- card using the drivers/fc4 layer (currently only SOCAL). The most
- common is either A5000 array or internal disks in E[3-6]000
- machines.
-
- To compile this support as a module, choose M here: the module will
- be called fcal.
-
-config SCSI_FCAL
- prompt "Generic FC-AL disk driver"
- depends on FC4!=n && SCSI && !SPARC
-
-endmenu
-
diff --git a/drivers/fc4/Makefile b/drivers/fc4/Makefile
deleted file mode 100644
index 0db3fbb553e..00000000000
--- a/drivers/fc4/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the Linux Fibre Channel device drivers.
-#
-
-fc4-objs := fc.o fc_syms.o
-
-obj-$(CONFIG_FC4) += fc4.o
-obj-$(CONFIG_FC4_SOC) += soc.o
-obj-$(CONFIG_FC4_SOCAL) += socal.o
diff --git a/drivers/fc4/fc-al.h b/drivers/fc4/fc-al.h
deleted file mode 100644
index 62d3ca436d7..00000000000
--- a/drivers/fc4/fc-al.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* fc-al.h: Definitions for Fibre Channel Arbitrated Loop topology.
- *
- * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- * Sources:
- * Fibre Channel Arbitrated Loop (FC-AL), ANSI, Rev. 4.5, 1995
- */
-
-#ifndef __FC_AL_H
-#define __FC_AL_H
-
-/* Loop initialization payloads */
-#define FC_AL_LISM 0x11010000 /* Select Master, 12B payload */
-#define FC_AL_LIFA 0x11020000 /* Fabric Assign AL_PA bitmap, 20B payload */
-#define FC_AL_LIPA 0x11030000 /* Previously Acquired AL_PA bitmap, 20B payload */
-#define FC_AL_LIHA 0x11040000 /* Hard Assigned AL_PA bitmap, 20B payload */
-#define FC_AL_LISA 0x11050000 /* Soft Assigned AL_PA bitmap, 20B payload */
-#define FC_AL_LIRP 0x11060000 /* Report AL_PA position map, 132B payload */
-#define FC_AL_LILP 0x11070000 /* Loop AL_PA position map, 132B payload */
-
-typedef struct {
- u32 magic;
- u8 len;
- u8 alpa[127];
-} fc_al_posmap;
-
-#endif /* !(__FC_H) */
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
deleted file mode 100644
index 82de9e1adb1..00000000000
--- a/drivers/fc4/fc.c
+++ /dev/null
@@ -1,1146 +0,0 @@
-/* fc.c: Generic Fibre Channel and FC4 SCSI driver.
- *
- * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
- *
- * There are two kinds of Fibre Channel adapters used in Linux. Either
- * the adapter is "smart" and does all FC bookkeeping by itself and
- * just presents a standard SCSI interface to the operating system
- * (that's e.g. the case with Qlogic FC cards), or leaves most of the FC
- * bookkeeping to the OS (e.g. soc, socal). Drivers for the former adapters
- * will look like normal SCSI drivers (with the exception of max_id will be
- * usually 127), the latter on the other side allows SCSI, IP over FC and other
- * protocols. This driver tree is for the latter adapters.
- *
- * This file should support both Point-to-Point and Arbitrated Loop topologies.
- *
- * Sources:
- * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
- * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
- * Fibre Channel Arbitrated Loop (FC-AL), Rev. 4.5, 1995
- * Fibre Channel Private Loop SCSI Direct Attach (FC-PLDA), Rev. 2.1, 1997
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/semaphore.h>
-#include "fcp_impl.h"
-#include <scsi/scsi_host.h>
-
-/* #define FCDEBUG */
-
-#define fc_printk printk ("%s: ", fc->name); printk
-
-#ifdef FCDEBUG
-#define FCD(x) fc_printk x;
-#define FCND(x) printk ("FC: "); printk x;
-#else
-#define FCD(x)
-#define FCND(x)
-#endif
-
-#ifdef __sparc__
-#define dma_alloc_consistent(d,s,p) sbus_alloc_consistent(d,s,p)
-#define dma_free_consistent(d,s,v,h) sbus_free_consistent(d,s,v,h)
-#define dma_map_single(d,v,s,dir) sbus_map_single(d,v,s,dir)
-#define dma_unmap_single(d,h,s,dir) sbus_unmap_single(d,h,s,dir)
-#define dma_map_sg(d,s,n,dir) sbus_map_sg(d,s,n,dir)
-#define dma_unmap_sg(d,s,n,dir) sbus_unmap_sg(d,s,n,dir)
-#else
-#define dma_alloc_consistent(d,s,p) pci_alloc_consistent(d,s,p)
-#define dma_free_consistent(d,s,v,h) pci_free_consistent(d,s,v,h)
-#define dma_map_single(d,v,s,dir) pci_map_single(d,v,s,dir)
-#define dma_unmap_single(d,h,s,dir) pci_unmap_single(d,h,s,dir)
-#define dma_map_sg(d,s,n,dir) pci_map_sg(d,s,n,dir)
-#define dma_unmap_sg(d,s,n,dir) pci_unmap_sg(d,s,n,dir)
-#endif
-
-#define FCP_CMND(SCpnt) ((fcp_cmnd *)&(SCpnt->SCp))
-#define FC_SCMND(SCpnt) ((fc_channel *)(SCpnt->device->host->hostdata[0]))
-#define SC_FCMND(fcmnd) ((struct scsi_cmnd *)((long)fcmnd - (long)&(((struct scsi_cmnd *)0)->SCp)))
-
-static int fcp_scsi_queue_it(fc_channel *, struct scsi_cmnd *, fcp_cmnd *, int);
-void fcp_queue_empty(fc_channel *);
-
-static void fcp_scsi_insert_queue (fc_channel *fc, fcp_cmnd *fcmd)
-{
- if (!fc->scsi_que) {
- fc->scsi_que = fcmd;
- fcmd->next = fcmd;
- fcmd->prev = fcmd;
- } else {
- fc->scsi_que->prev->next = fcmd;
- fcmd->prev = fc->scsi_que->prev;
- fc->scsi_que->prev = fcmd;
- fcmd->next = fc->scsi_que;
- }
-}
-
-static void fcp_scsi_remove_queue (fc_channel *fc, fcp_cmnd *fcmd)
-{
- if (fcmd == fcmd->next) {
- fc->scsi_que = NULL;
- return;
- }
- if (fcmd == fc->scsi_que)
- fc->scsi_que = fcmd->next;
- fcmd->prev->next = fcmd->next;
- fcmd->next->prev = fcmd->prev;
-}
-
-fc_channel *fc_channels = NULL;
-
-#define LSMAGIC 620829043
-typedef struct {
- /* Must be first */
- struct semaphore sem;
- int magic;
- int count;
- logi *logi;
- fcp_cmnd *fcmds;
- atomic_t todo;
- struct timer_list timer;
- unsigned char grace[0];
-} ls;
-
-#define LSOMAGIC 654907799
-typedef struct {
- /* Must be first */
- struct semaphore sem;
- int magic;
- int count;
- fcp_cmnd *fcmds;
- atomic_t todo;
- struct timer_list timer;
-} lso;
-
-#define LSEMAGIC 84482456
-typedef struct {
- /* Must be first */
- struct semaphore sem;
- int magic;
- int status;
- struct timer_list timer;
-} lse;
-
-static void fcp_login_timeout(unsigned long data)
-{
- ls *l = (ls *)data;
- FCND(("Login timeout\n"))
- up(&l->sem);
-}
-
-static void fcp_login_done(fc_channel *fc, int i, int status)
-{
- fcp_cmnd *fcmd;
- logi *plogi;
- fc_hdr *fch;
- ls *l = (ls *)fc->ls;
-
- FCD(("Login done %d %d\n", i, status))
- if (i < l->count) {
- if (fc->state == FC_STATE_FPORT_OK) {
- FCD(("Additional FPORT_OK received with status %d\n", status))
- return;
- }
- switch (status) {
- case FC_STATUS_OK: /* Oh, we found a fabric */
- case FC_STATUS_P_RJT: /* Oh, we haven't found any */
- fc->state = FC_STATE_FPORT_OK;
- fcmd = l->fcmds + i;
- plogi = l->logi + 3 * i;
- dma_unmap_single (fc->dev, fcmd->cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- plogi->code = LS_PLOGI;
- memcpy (&plogi->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
- memcpy (&plogi->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
- memcpy (&plogi->common, fc->common_svc, sizeof(common_svc_parm));
- memcpy (&plogi->class1, fc->class_svcs, 3*sizeof(svc_parm));
- fch = &fcmd->fch;
- fcmd->token += l->count;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, fc->did);
- FILL_FCHDR_SID(fch, fc->sid);
-#ifdef FCDEBUG
- {
- int i;
- unsigned *x = (unsigned *)plogi;
- printk ("logi: ");
- for (i = 0; i < 21; i++)
- printk ("%08x ", x[i]);
- printk ("\n");
- }
-#endif
- fcmd->cmd = dma_map_single (fc->dev, plogi, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- fcmd->rsp = fcmd->cmd + 2 * sizeof(logi);
- if (fc->hw_enque (fc, fcmd))
- printk ("FC: Cannot enque PLOGI packet on %s\n", fc->name);
- break;
- case FC_STATUS_ERR_OFFLINE:
- fc->state = FC_STATE_MAYBEOFFLINE;
- FCD (("FC is offline %d\n", l->grace[i]))
- break;
- default:
- printk ("FLOGI failed for %s with status %d\n", fc->name, status);
- /* Do some sort of error recovery here */
- break;
- }
- } else {
- i -= l->count;
- if (fc->state != FC_STATE_FPORT_OK) {
- FCD(("Unexpected N-PORT rsp received"))
- return;
- }
- switch (status) {
- case FC_STATUS_OK:
- plogi = l->logi + 3 * i;
- dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- if (!fc->wwn_dest.lo && !fc->wwn_dest.hi) {
- memcpy (&fc->wwn_dest, &plogi[1].node_wwn, sizeof(fc_wwn));
- FCD(("Dest WWN %08x%08x\n", *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo))
- } else if (fc->wwn_dest.lo != plogi[1].node_wwn.lo ||
- fc->wwn_dest.hi != plogi[1].node_wwn.hi) {
- printk ("%s: mismatch in wwns. Got %08x%08x, expected %08x%08x\n",
- fc->name,
- *(u32 *)&plogi[1].node_wwn, plogi[1].node_wwn.lo,
- *(u32 *)&fc->wwn_dest, fc->wwn_dest.lo);
- }
- fc->state = FC_STATE_ONLINE;
- printk ("%s: ONLINE\n", fc->name);
- if (atomic_dec_and_test (&l->todo))
- up(&l->sem);
- break;
- case FC_STATUS_ERR_OFFLINE:
- fc->state = FC_STATE_OFFLINE;
- dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- printk ("%s: FC is offline\n", fc->name);
- if (atomic_dec_and_test (&l->todo))
- up(&l->sem);
- break;
- default:
- printk ("PLOGI failed for %s with status %d\n", fc->name, status);
- /* Do some sort of error recovery here */
- break;
- }
- }
-}
-
-static void fcp_report_map_done(fc_channel *fc, int i, int status)
-{
- fcp_cmnd *fcmd;
- fc_hdr *fch;
- unsigned char j;
- ls *l = (ls *)fc->ls;
- fc_al_posmap *p;
-
- FCD(("Report map done %d %d\n", i, status))
- switch (status) {
- case FC_STATUS_OK: /* Ok, let's have a fun on a loop */
- dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- p = (fc_al_posmap *)(l->logi + 3 * i);
-#ifdef FCDEBUG
- {
- u32 *u = (u32 *)p;
- FCD(("%08x\n", u[0]))
- u ++;
- FCD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- }
-#endif
- if ((p->magic & 0xffff0000) != FC_AL_LILP || !p->len) {
- printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic);
- fc->state = FC_STATE_OFFLINE;
- } else {
- fc->posmap = kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
- if (!fc->posmap) {
- printk("FC: Not enough memory, offlining channel\n");
- fc->state = FC_STATE_OFFLINE;
- } else {
- int k;
- /* FIXME: This is where SOCAL transfers our AL-PA.
- Keep it here till we found out what other cards do... */
- fc->sid = (p->magic & 0xff);
- for (i = 0; i < p->len; i++)
- if (p->alpa[i] == fc->sid)
- break;
- k = p->len;
- if (i == p->len)
- i = 0;
- else {
- p->len--;
- i++;
- }
- fc->posmap->len = p->len;
- for (j = 0; j < p->len; j++) {
- if (i == k) i = 0;
- fc->posmap->list[j] = p->alpa[i++];
- }
- fc->state = FC_STATE_ONLINE;
- }
- }
- printk ("%s: ONLINE\n", fc->name);
- if (atomic_dec_and_test (&l->todo))
- up(&l->sem);
- break;
- case FC_STATUS_POINTTOPOINT: /* We're Point-to-Point, no AL... */
- FCD(("SID %d DID %d\n", fc->sid, fc->did))
- fcmd = l->fcmds + i;
- dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- fch = &fcmd->fch;
- memset(l->logi + 3 * i, 0, 3 * sizeof(logi));
- FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
- FILL_FCHDR_SID(fch, 0);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- l->logi [3 * i].code = LS_FLOGI;
- fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- fcmd->rsp = fcmd->cmd + sizeof(logi);
- fcmd->cmdlen = sizeof(logi);
- fcmd->rsplen = sizeof(logi);
- fcmd->data = (dma_addr_t)NULL;
- fcmd->class = FC_CLASS_SIMPLE;
- fcmd->proto = TYPE_EXTENDED_LS;
- if (fc->hw_enque (fc, fcmd))
- printk ("FC: Cannot enque FLOGI packet on %s\n", fc->name);
- break;
- case FC_STATUS_ERR_OFFLINE:
- fc->state = FC_STATE_MAYBEOFFLINE;
- FCD (("FC is offline %d\n", l->grace[i]))
- break;
- default:
- printk ("FLOGI failed for %s with status %d\n", fc->name, status);
- /* Do some sort of error recovery here */
- break;
- }
-}
-
-void fcp_register(fc_channel *fc, u8 type, int unregister)
-{
- int size, i;
- int slots = (fc->can_queue * 3) >> 1;
-
- FCND(("Going to %sregister\n", unregister ? "un" : ""))
-
- if (type == TYPE_SCSI_FCP) {
- if (!unregister) {
- fc->scsi_cmd_pool = (fcp_cmd *)
- dma_alloc_consistent (fc->dev,
- slots * (sizeof (fcp_cmd) + fc->rsp_size),
- &fc->dma_scsi_cmd);
- fc->scsi_rsp_pool = (char *)(fc->scsi_cmd_pool + slots);
- fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd);
- fc->scsi_bitmap_end = (slots + 63) & ~63;
- size = fc->scsi_bitmap_end / 8;
- fc->scsi_bitmap = kzalloc (size, GFP_KERNEL);
- set_bit (0, fc->scsi_bitmap);
- for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++)
- set_bit (i, fc->scsi_bitmap);
- fc->scsi_free = fc->can_queue;
- fc->cmd_slots = kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
- fc->abort_count = 0;
- } else {
- fc->scsi_name[0] = 0;
- kfree (fc->scsi_bitmap);
- kfree (fc->cmd_slots);
- FCND(("Unregistering\n"));
-#if 0
- if (fc->rst_pkt) {
- if (fc->rst_pkt->eh_state == SCSI_STATE_UNUSED)
- kfree(fc->rst_pkt);
- else {
- /* Can't happen. Some memory would be lost. */
- printk("FC: Reset in progress. Now?!");
- }
- }
-#endif
- FCND(("Unregistered\n"));
- }
- } else
- printk ("FC: %segistering unknown type %02x\n", unregister ? "Unr" : "R", type);
-}
-
-static void fcp_scsi_done(struct scsi_cmnd *SCpnt);
-
-static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hdr *fch)
-{
- fcp_cmnd *fcmd;
- fcp_rsp *rsp;
- int host_status;
- struct scsi_cmnd *SCpnt;
- int sense_len;
- int rsp_status;
-
- fcmd = fc->cmd_slots[token];
- if (!fcmd) return;
- rsp = (fcp_rsp *) (fc->scsi_rsp_pool + fc->rsp_size * token);
- SCpnt = SC_FCMND(fcmd);
-
- if (SCpnt->done != fcp_scsi_done)
- return;
-
- rsp_status = rsp->fcp_status;
- FCD(("rsp_status %08x status %08x\n", rsp_status, status))
- switch (status) {
- case FC_STATUS_OK:
- host_status=DID_OK;
-
- if (rsp_status & FCP_STATUS_RESID) {
-#ifdef FCDEBUG
- FCD(("Resid %d\n", rsp->fcp_resid))
- {
- fcp_cmd *cmd = fc->scsi_cmd_pool + token;
- int i;
-
- printk ("Command ");
- for (i = 0; i < sizeof(fcp_cmd); i+=4)
- printk ("%08x ", *(u32 *)(((char *)cmd)+i));
- printk ("\nResponse ");
- for (i = 0; i < fc->rsp_size; i+=4)
- printk ("%08x ", *(u32 *)(((char *)rsp)+i));
- printk ("\n");
- }
-#endif
- }
-
- if (rsp_status & FCP_STATUS_SENSE_LEN) {
- sense_len = rsp->fcp_sense_len;
- if (sense_len > sizeof(SCpnt->sense_buffer)) sense_len = sizeof(SCpnt->sense_buffer);
- memcpy(SCpnt->sense_buffer, ((char *)(rsp+1)), sense_len);
- }
-
- if (fcmd->data)
- dma_unmap_sg(fc->dev, scsi_sglist(SCpnt),
- scsi_sg_count(SCpnt),
- SCpnt->sc_data_direction);
- break;
- default:
- host_status=DID_ERROR; /* FIXME */
- FCD(("Wrong FC status %d for token %d\n", status, token))
- break;
- }
-
- if (status_byte(rsp_status) == QUEUE_FULL) {
- printk ("%s: (%d,%d) Received rsp_status 0x%x\n", fc->name, SCpnt->device->channel, SCpnt->device->id, rsp_status);
- }
-
- SCpnt->result = (host_status << 16) | (rsp_status & 0xff);
-#ifdef FCDEBUG
- if (host_status || SCpnt->result || rsp_status) printk("FC: host_status %d, packet status %d\n",
- host_status, SCpnt->result);
-#endif
- SCpnt->done = fcmd->done;
- fcmd->done=NULL;
- clear_bit(token, fc->scsi_bitmap);
- fc->scsi_free++;
- FCD(("Calling scsi_done with %08x\n", SCpnt->result))
- SCpnt->scsi_done(SCpnt);
-}
-
-void fcp_receive_solicited(fc_channel *fc, int proto, int token, int status, fc_hdr *fch)
-{
- int magic;
- FCD(("receive_solicited %d %d %d\n", proto, token, status))
- switch (proto) {
- case TYPE_SCSI_FCP:
- fcp_scsi_receive(fc, token, status, fch); break;
- case TYPE_EXTENDED_LS:
- case PROTO_REPORT_AL_MAP:
- magic = 0;
- if (fc->ls)
- magic = ((ls *)(fc->ls))->magic;
- if (magic == LSMAGIC) {
- ls *l = (ls *)fc->ls;
- int i = (token >= l->count) ? token - l->count : token;
-
- /* Let's be sure */
- if ((unsigned)i < l->count && l->fcmds[i].fc == fc) {
- if (proto == TYPE_EXTENDED_LS)
- fcp_login_done(fc, token, status);
- else
- fcp_report_map_done(fc, token, status);
- break;
- }
- }
- FCD(("fc %p fc->ls %p fc->cmd_slots %p\n", fc, fc->ls, fc->cmd_slots))
- if (proto == TYPE_EXTENDED_LS && !fc->ls && fc->cmd_slots) {
- fcp_cmnd *fcmd;
-
- fcmd = fc->cmd_slots[token];
- if (fcmd && fcmd->ls && ((ls *)(fcmd->ls))->magic == LSEMAGIC) {
- lse *l = (lse *)fcmd->ls;
-
- l->status = status;
- up (&l->sem);
- }
- }
- break;
- case PROTO_OFFLINE:
- if (fc->ls && ((lso *)(fc->ls))->magic == LSOMAGIC) {
- lso *l = (lso *)fc->ls;
-
- if ((unsigned)token < l->count && l->fcmds[token].fc == fc) {
- /* Wow, OFFLINE response arrived :) */
- FCD(("OFFLINE Response arrived\n"))
- fc->state = FC_STATE_OFFLINE;
- if (atomic_dec_and_test (&l->todo))
- up(&l->sem);
- }
- }
- break;
-
- default:
- break;
- }
-}
-
-void fcp_state_change(fc_channel *fc, int state)
-{
- FCD(("state_change %d %d\n", state, fc->state))
- if (state == FC_STATE_ONLINE && fc->state == FC_STATE_MAYBEOFFLINE)
- fc->state = FC_STATE_UNINITED;
- else if (state == FC_STATE_ONLINE)
- printk (KERN_WARNING "%s: state change to ONLINE\n", fc->name);
- else
- printk (KERN_ERR "%s: state change to OFFLINE\n", fc->name);
-}
-
-int fcp_initialize(fc_channel *fcchain, int count)
-{
- fc_channel *fc;
- fcp_cmnd *fcmd;
- int i, retry, ret;
- ls *l;
-
- FCND(("fcp_inititialize %08lx\n", (long)fcp_init))
- FCND(("fc_channels %08lx\n", (long)fc_channels))
- FCND((" SID %d DID %d\n", fcchain->sid, fcchain->did))
- l = kzalloc(sizeof (ls) + count, GFP_KERNEL);
- if (!l) {
- printk ("FC: Cannot allocate memory for initialization\n");
- return -ENOMEM;
- }
- l->magic = LSMAGIC;
- l->count = count;
- FCND(("FCP Init for %d channels\n", count))
- init_MUTEX_LOCKED(&l->sem);
- init_timer(&l->timer);
- l->timer.function = fcp_login_timeout;
- l->timer.data = (unsigned long)l;
- atomic_set (&l->todo, count);
- l->logi = kzalloc (count * 3 * sizeof(logi), GFP_KERNEL);
- l->fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
- if (!l->logi || !l->fcmds) {
- kfree (l->logi);
- kfree (l->fcmds);
- kfree (l);
- printk ("FC: Cannot allocate DMA memory for initialization\n");
- return -ENOMEM;
- }
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- fc->state = FC_STATE_UNINITED;
- fc->rst_pkt = NULL; /* kmalloc when first used */
- }
- /* First try if we are in a AL topology */
- FCND(("Initializing REPORT_MAP packets\n"))
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- fcmd = l->fcmds + i;
- fc->login = fcmd;
- fc->ls = (void *)l;
- /* Assumes sizeof(fc_al_posmap) < 3 * sizeof(logi), which is true */
- fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi),
- DMA_BIDIRECTIONAL);
- fcmd->proto = PROTO_REPORT_AL_MAP;
- fcmd->token = i;
- fcmd->fc = fc;
- }
- for (retry = 0; retry < 8; retry++) {
- int nqueued = 0;
- FCND(("Sending REPORT_MAP/FLOGI/PLOGI packets\n"))
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- if (fc->state == FC_STATE_ONLINE || fc->state == FC_STATE_OFFLINE)
- continue;
- disable_irq(fc->irq);
- if (fc->state == FC_STATE_MAYBEOFFLINE) {
- if (!l->grace[i]) {
- l->grace[i]++;
- FCD(("Grace\n"))
- } else {
- fc->state = FC_STATE_OFFLINE;
- enable_irq(fc->irq);
- dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
- if (atomic_dec_and_test (&l->todo))
- goto all_done;
- }
- }
- ret = fc->hw_enque (fc, fc->login);
- enable_irq(fc->irq);
- if (!ret) {
- nqueued++;
- continue;
- }
- if (ret == -ENOSYS && fc->login->proto == PROTO_REPORT_AL_MAP) {
- /* Oh yes, this card handles Point-to-Point only, so let's try that. */
- fc_hdr *fch;
-
- FCD(("SID %d DID %d\n", fc->sid, fc->did))
- fcmd = l->fcmds + i;
- dma_unmap_single(fc->dev, fcmd->cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
- fch = &fcmd->fch;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, FS_FABRIC_F_PORT);
- FILL_FCHDR_SID(fch, 0);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- l->logi [3 * i].code = LS_FLOGI;
- fcmd->cmd = dma_map_single (fc->dev, l->logi + 3 * i, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
- fcmd->rsp = fcmd->cmd + sizeof(logi);
- fcmd->cmdlen = sizeof(logi);
- fcmd->rsplen = sizeof(logi);
- fcmd->data = (dma_addr_t)NULL;
- fcmd->class = FC_CLASS_SIMPLE;
- fcmd->proto = TYPE_EXTENDED_LS;
- } else
- printk ("FC: Cannot enque FLOGI/REPORT_MAP packet on %s\n", fc->name);
- }
-
- if (nqueued) {
- l->timer.expires = jiffies + 5 * HZ;
- add_timer(&l->timer);
-
- down(&l->sem);
- if (!atomic_read(&l->todo)) {
- FCND(("All channels answered in time\n"))
- break; /* All fc channels have answered us */
- }
- }
- }
-all_done:
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- fc->ls = NULL;
- switch (fc->state) {
- case FC_STATE_ONLINE: break;
- case FC_STATE_OFFLINE: break;
- default: dma_unmap_single (fc->dev, l->fcmds[i].cmd, 3 * sizeof(logi), DMA_BIDIRECTIONAL);
- break;
- }
- }
- del_timer(&l->timer);
- kfree (l->logi);
- kfree (l->fcmds);
- kfree (l);
- return 0;
-}
-
-int fcp_forceoffline(fc_channel *fcchain, int count)
-{
- fc_channel *fc;
- fcp_cmnd *fcmd;
- int i, ret;
- lso l;
-
- memset (&l, 0, sizeof(lso));
- l.count = count;
- l.magic = LSOMAGIC;
- FCND(("FCP Force Offline for %d channels\n", count))
- init_MUTEX_LOCKED(&l.sem);
- init_timer(&l.timer);
- l.timer.function = fcp_login_timeout;
- l.timer.data = (unsigned long)&l;
- atomic_set (&l.todo, count);
- l.fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
- if (!l.fcmds) {
- printk ("FC: Cannot allocate memory for forcing offline\n");
- return -ENOMEM;
- }
- FCND(("Initializing OFFLINE packets\n"))
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
- fc->state = FC_STATE_UNINITED;
- fcmd = l.fcmds + i;
- fc->login = fcmd;
- fc->ls = (void *)&l;
- fcmd->did = fc->did;
- fcmd->class = FC_CLASS_OFFLINE;
- fcmd->proto = PROTO_OFFLINE;
- fcmd->token = i;
- fcmd->fc = fc;
- disable_irq(fc->irq);
- ret = fc->hw_enque (fc, fc->login);
- enable_irq(fc->irq);
- if (ret) printk ("FC: Cannot enque OFFLINE packet on %s\n", fc->name);
- }
-
- l.timer.expires = jiffies + 5 * HZ;
- add_timer(&l.timer);
- down(&l.sem);
- del_timer(&l.timer);
-
- for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++)
- fc->ls = NULL;
- kfree (l.fcmds);
- return 0;
-}
-
-int fcp_init(fc_channel *fcchain)
-{
- fc_channel *fc;
- int count=0;
- int ret;
-
- for (fc = fcchain; fc; fc = fc->next) {
- fc->fcp_register = fcp_register;
- count++;
- }
-
- ret = fcp_initialize (fcchain, count);
- if (ret)
- return ret;
-
- if (!fc_channels)
- fc_channels = fcchain;
- else {
- for (fc = fc_channels; fc->next; fc = fc->next);
- fc->next = fcchain;
- }
- return ret;
-}
-
-void fcp_release(fc_channel *fcchain, int count) /* count must > 0 */
-{
- fc_channel *fc;
- fc_channel *fcx;
-
- for (fc = fcchain; --count && fc->next; fc = fc->next);
- if (count) {
- printk("FC: nothing to release\n");
- return;
- }
-
- if (fc_channels == fcchain)
- fc_channels = fc->next;
- else {
- for (fcx = fc_channels; fcx->next != fcchain; fcx = fcx->next);
- fcx->next = fc->next;
- }
- fc->next = NULL;
-
- /*
- * We've just grabbed fcchain out of the fc_channel list
- * and zero-terminated it, while destroying the count.
- *
- * Freeing the fc's is the low level driver's responsibility.
- */
-}
-
-
-static void fcp_scsi_done(struct scsi_cmnd *SCpnt)
-{
- if (FCP_CMND(SCpnt)->done)
- FCP_CMND(SCpnt)->done(SCpnt);
-}
-
-static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt,
- fcp_cmnd *fcmd, int prepare)
-{
- long i;
- fcp_cmd *cmd;
- u32 fcp_cntl;
- if (prepare) {
- i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end);
- set_bit (i, fc->scsi_bitmap);
- fcmd->token = i;
- cmd = fc->scsi_cmd_pool + i;
-
- if (fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd)) {
- /* Invalid channel/id/lun and couldn't map it into fcp_addr */
- clear_bit (i, fc->scsi_bitmap);
- SCpnt->result = (DID_BAD_TARGET << 16);
- SCpnt->scsi_done(SCpnt);
- return 0;
- }
- fc->scsi_free--;
- fc->cmd_slots[fcmd->token] = fcmd;
-
- if (SCpnt->device->tagged_supported) {
- if (jiffies - fc->ages[SCpnt->device->channel * fc->targets + SCpnt->device->id] > (5 * 60 * HZ)) {
- fc->ages[SCpnt->device->channel * fc->targets + SCpnt->device->id] = jiffies;
- fcp_cntl = FCP_CNTL_QTYPE_ORDERED;
- } else
- fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
- } else
- fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED;
-
- if (!scsi_bufflen(SCpnt)) {
- cmd->fcp_cntl = fcp_cntl;
- fcmd->data = (dma_addr_t)NULL;
- } else {
- struct scatterlist *sg;
- int nents;
-
- switch (SCpnt->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- case WRITE_12:
- cmd->fcp_cntl = (FCP_CNTL_WRITE | fcp_cntl); break;
- default:
- cmd->fcp_cntl = (FCP_CNTL_READ | fcp_cntl); break;
- }
-
- sg = scsi_sglist(SCpnt);
- nents = dma_map_sg(fc->dev, sg, scsi_sg_count(SCpnt),
- SCpnt->sc_data_direction);
- fcmd->data = sg_dma_address(sg);
- cmd->fcp_data_len = sg_dma_len(sg);
- }
- memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
- memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
- FCD(("XXX: %04x.%04x.%04x.%04x - %08x%08x%08x\n", cmd->fcp_addr[0], cmd->fcp_addr[1], cmd->fcp_addr[2], cmd->fcp_addr[3], *(u32 *)SCpnt->cmnd, *(u32 *)(SCpnt->cmnd+4), *(u32 *)(SCpnt->cmnd+8)))
- }
- FCD(("Trying to enque %p\n", fcmd))
- if (!fc->scsi_que) {
- if (!fc->hw_enque (fc, fcmd)) {
- FCD(("hw_enque succeeded for %p\n", fcmd))
- return 0;
- }
- }
- FCD(("Putting into que1 %p\n", fcmd))
- fcp_scsi_insert_queue (fc, fcmd);
- return 0;
-}
-
-int fcp_scsi_queuecommand(struct scsi_cmnd *SCpnt,
- void (* done)(struct scsi_cmnd *))
-{
- fcp_cmnd *fcmd = FCP_CMND(SCpnt);
- fc_channel *fc = FC_SCMND(SCpnt);
-
- FCD(("Entering SCSI queuecommand %p\n", fcmd))
- if (SCpnt->done != fcp_scsi_done) {
- fcmd->done = SCpnt->done;
- SCpnt->done = fcp_scsi_done;
- SCpnt->scsi_done = done;
- fcmd->proto = TYPE_SCSI_FCP;
- if (!fc->scsi_free) {
- FCD(("FC: !scsi_free, putting cmd on ML queue\n"))
-#if (FCP_SCSI_USE_NEW_EH_CODE == 0)
- printk("fcp_scsi_queue_command: queue full, losing cmd, bad\n");
-#endif
- return 1;
- }
- return fcp_scsi_queue_it(fc, SCpnt, fcmd, 1);
- }
- return fcp_scsi_queue_it(fc, SCpnt, fcmd, 0);
-}
-
-void fcp_queue_empty(fc_channel *fc)
-{
- fcp_cmnd *fcmd;
-
- FCD(("Queue empty\n"))
- while ((fcmd = fc->scsi_que)) {
- /* The hw told us we can try again queue some packet */
- if (fc->hw_enque (fc, fcmd))
- break;
- fcp_scsi_remove_queue (fc, fcmd);
- }
-}
-
-int fcp_scsi_abort(struct scsi_cmnd *SCpnt)
-{
- /* Internal bookkeeping only. Lose 1 cmd_slots slot. */
- fcp_cmnd *fcmd = FCP_CMND(SCpnt);
- fc_channel *fc = FC_SCMND(SCpnt);
-
- /*
- * We react to abort requests by simply forgetting
- * about the command and pretending everything's sweet.
- * This may or may not be silly. We can't, however,
- * immediately reuse the command's cmd_slots slot,
- * as its result may arrive later and we cannot
- * check whether it is the aborted one, can't we?
- *
- * Therefore, after the first few aborts are done,
- * we tell the scsi error handler to do something clever.
- * It will eventually call host reset, refreshing
- * cmd_slots for us.
- *
- * There is a theoretical chance that we sometimes allow
- * more than can_queue packets to the jungle this way,
- * but the worst outcome possible is a series of
- * more aborts and eventually the dev_reset catharsis.
- */
-
- if (++fc->abort_count < (fc->can_queue >> 1)) {
- SCpnt->result = DID_ABORT;
- fcmd->done(SCpnt);
- printk("FC: soft abort\n");
- return SUCCESS;
- } else {
- printk("FC: hard abort refused\n");
- return FAILED;
- }
-}
-
-#if 0
-void fcp_scsi_reset_done(struct scsi_cmnd *SCpnt)
-{
- fc_channel *fc = FC_SCMND(SCpnt);
-
- fc->rst_pkt->eh_state = SCSI_STATE_FINISHED;
- up(fc->rst_pkt->device->host->eh_action);
-}
-#endif
-
-#define FCP_RESET_TIMEOUT (2*HZ)
-
-int fcp_scsi_dev_reset(struct scsi_cmnd *SCpnt)
-{
-#if 0 /* broken junk, but if davem wants to compile this driver, let him.. */
- unsigned long flags;
- fcp_cmd *cmd;
- fcp_cmnd *fcmd;
- fc_channel *fc = FC_SCMND(SCpnt);
- DECLARE_MUTEX_LOCKED(sem);
-
- if (!fc->rst_pkt) {
- fc->rst_pkt = kmalloc(sizeof(SCpnt), GFP_KERNEL);
- if (!fc->rst_pkt) return FAILED;
-
- fcmd = FCP_CMND(fc->rst_pkt);
-
-
- fcmd->token = 0;
- cmd = fc->scsi_cmd_pool + 0;
- FCD(("Preparing rst packet\n"))
- fc->encode_addr (SCpnt, cmd->fcp_addr, fc, fcmd);
- fc->rst_pkt->device = SCpnt->device;
- fc->rst_pkt->cmd_len = 0;
-
- fc->cmd_slots[0] = fcmd;
-
- cmd->fcp_cntl = FCP_CNTL_QTYPE_ORDERED | FCP_CNTL_RESET;
- fcmd->data = (dma_addr_t)NULL;
- fcmd->proto = TYPE_SCSI_FCP;
-
- memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
- memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len);
- FCD(("XXX: %04x.%04x.%04x.%04x - %08x%08x%08x\n", cmd->fcp_addr[0], cmd->fcp_addr[1], cmd->fcp_addr[2], cmd->fcp_addr[3], *(u32 *)SCpnt->cmnd, *(u32 *)(SCpnt->cmnd+4), *(u32 *)(SCpnt->cmnd+8)))
- } else {
- fcmd = FCP_CMND(fc->rst_pkt);
- if (fc->rst_pkt->eh_state == SCSI_STATE_QUEUED)
- return FAILED; /* or SUCCESS. Only these */
- }
- fc->rst_pkt->done = NULL;
-
-
- fc->rst_pkt->eh_state = SCSI_STATE_QUEUED;
- init_timer(&fc->rst_pkt->eh_timeout);
- fc->rst_pkt->eh_timeout.data = (unsigned long) fc->rst_pkt;
- fc->rst_pkt->eh_timeout.expires = jiffies + FCP_RESET_TIMEOUT;
- fc->rst_pkt->eh_timeout.function = (void (*)(unsigned long))fcp_scsi_reset_done;
-
- add_timer(&fc->rst_pkt->eh_timeout);
-
- /*
- * Set up the semaphore so we wait for the command to complete.
- */
-
- fc->rst_pkt->device->host->eh_action = &sem;
-
- fc->rst_pkt->done = fcp_scsi_reset_done;
-
- spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
- fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0);
- spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
-
- down(&sem);
-
- fc->rst_pkt->device->host->eh_action = NULL;
- del_timer(&fc->rst_pkt->eh_timeout);
-
- /*
- * See if timeout. If so, tell the host to forget about it.
- * In other words, we don't want a callback any more.
- */
- if (fc->rst_pkt->eh_state == SCSI_STATE_TIMEOUT ) {
- fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
- return FAILED;
- }
- fc->rst_pkt->eh_state = SCSI_STATE_UNUSED;
-#endif
- return SUCCESS;
-}
-
-static int __fcp_scsi_host_reset(struct scsi_cmnd *SCpnt)
-{
- fc_channel *fc = FC_SCMND(SCpnt);
- fcp_cmnd *fcmd = FCP_CMND(SCpnt);
- int i;
-
- printk ("FC: host reset\n");
-
- for (i=0; i < fc->can_queue; i++) {
- if (fc->cmd_slots[i] && SCpnt->result != DID_ABORT) {
- SCpnt->result = DID_RESET;
- fcmd->done(SCpnt);
- fc->cmd_slots[i] = NULL;
- }
- }
- fc->reset(fc);
- fc->abort_count = 0;
- if (fcp_initialize(fc, 1)) return SUCCESS;
- else return FAILED;
-}
-
-int fcp_scsi_host_reset(struct scsi_cmnd *SCpnt)
-{
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
- rc = __fcp_scsi_host_reset(SCpnt);
- spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
-
- return rc;
-}
-
-static int fcp_els_queue_it(fc_channel *fc, fcp_cmnd *fcmd)
-{
- long i;
-
- i = find_first_zero_bit (fc->scsi_bitmap, fc->scsi_bitmap_end);
- set_bit (i, fc->scsi_bitmap);
- fcmd->token = i;
- fc->scsi_free--;
- fc->cmd_slots[fcmd->token] = fcmd;
- return fcp_scsi_queue_it(fc, NULL, fcmd, 0);
-}
-
-static int fc_do_els(fc_channel *fc, unsigned int alpa, void *data, int len)
-{
- fcp_cmnd _fcmd, *fcmd;
- fc_hdr *fch;
- lse l;
- int i;
-
- fcmd = &_fcmd;
- memset(fcmd, 0, sizeof(fcp_cmnd));
- FCD(("PLOGI SID %d DID %d\n", fc->sid, alpa))
- fch = &fcmd->fch;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_ELS_REQ, alpa);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_EXTENDED_LS, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- fcmd->cmd = dma_map_single (fc->dev, data, 2 * len, DMA_BIDIRECTIONAL);
- fcmd->rsp = fcmd->cmd + len;
- fcmd->cmdlen = len;
- fcmd->rsplen = len;
- fcmd->data = (dma_addr_t)NULL;
- fcmd->fc = fc;
- fcmd->class = FC_CLASS_SIMPLE;
- fcmd->proto = TYPE_EXTENDED_LS;
-
- memset (&l, 0, sizeof(lse));
- l.magic = LSEMAGIC;
- init_MUTEX_LOCKED(&l.sem);
- l.timer.function = fcp_login_timeout;
- l.timer.data = (unsigned long)&l;
- l.status = FC_STATUS_TIMED_OUT;
- fcmd->ls = (void *)&l;
-
- disable_irq(fc->irq);
- fcp_els_queue_it(fc, fcmd);
- enable_irq(fc->irq);
-
- for (i = 0;;) {
- l.timer.expires = jiffies + 5 * HZ;
- add_timer(&l.timer);
- down(&l.sem);
- del_timer(&l.timer);
- if (l.status != FC_STATUS_TIMED_OUT) break;
- if (++i == 3) break;
- disable_irq(fc->irq);
- fcp_scsi_queue_it(fc, NULL, fcmd, 0);
- enable_irq(fc->irq);
- }
-
- clear_bit(fcmd->token, fc->scsi_bitmap);
- fc->scsi_free++;
- dma_unmap_single (fc->dev, fcmd->cmd, 2 * len, DMA_BIDIRECTIONAL);
- return l.status;
-}
-
-int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport)
-{
- logi *l;
- int status;
-
- l = kzalloc(2 * sizeof(logi), GFP_KERNEL);
- if (!l) return -ENOMEM;
- l->code = LS_PLOGI;
- memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
- memcpy (&l->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
- memcpy (&l->common, fc->common_svc, sizeof(common_svc_parm));
- memcpy (&l->class1, fc->class_svcs, 3*sizeof(svc_parm));
- status = fc_do_els(fc, alpa, l, sizeof(logi));
- if (status == FC_STATUS_OK) {
- if (l[1].code == LS_ACC) {
-#ifdef FCDEBUG
- u32 *u = (u32 *)&l[1].nport_wwn;
- FCD(("AL-PA %02x: Port WWN %08x%08x Node WWN %08x%08x\n", alpa,
- u[0], u[1], u[2], u[3]))
-#endif
- memcpy(nport, &l[1].nport_wwn, sizeof(fc_wwn));
- memcpy(node, &l[1].node_wwn, sizeof(fc_wwn));
- } else
- status = FC_STATUS_BAD_RSP;
- }
- kfree(l);
- return status;
-}
-
-typedef struct {
- unsigned int code;
- unsigned params[4];
-} prli;
-
-int fc_do_prli(fc_channel *fc, unsigned char alpa)
-{
- prli *p;
- int status;
-
- p = kzalloc(2 * sizeof(prli), GFP_KERNEL);
- if (!p) return -ENOMEM;
- p->code = LS_PRLI;
- p->params[0] = 0x08002000;
- p->params[3] = 0x00000022;
- status = fc_do_els(fc, alpa, p, sizeof(prli));
- if (status == FC_STATUS_OK && p[1].code != LS_PRLI_ACC && p[1].code != LS_ACC)
- status = FC_STATUS_BAD_RSP;
- kfree(p);
- return status;
-}
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/fc4/fc.h b/drivers/fc4/fc.h
deleted file mode 100644
index 13f89d4c8cb..00000000000
--- a/drivers/fc4/fc.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/* fc.h: Definitions for Fibre Channel Physical and Signaling Interface.
- *
- * Copyright (C) 1996-1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
- *
- * Sources:
- * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
- * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
- */
-
-#ifndef __FC_H
-#define __FC_H
-
-/* World Wide Name */
-#define NAAID_IEEE 1
-#define NAAID_IEEE_EXT 2
-#define NAAID_LOCAL 3
-#define NAAID_IP 4
-#define NAAID_IEEE_REG 5
-#define NAAID_IEEE_REG_EXT 6
-#define NAAID_CCITT 12
-#define NAAID_CCITT_GRP 14
-
-/* This is NAAID_IEEE_EXT scheme */
-typedef struct {
- u32 naaid:4;
- u32 nportid:12;
- u32 hi:16;
- u32 lo;
-} fc_wwn;
-
-/* Frame header for FC-PH frames */
-
-/* r_ctl field */
-#define R_CTL_DEVICE_DATA 0x00 /* FC4 Device_Data frame */
-#define R_CTL_EXTENDED_SVC 0x20 /* Extended Link_Data frame */
-#define R_CTL_FC4_SVC 0x30 /* FC4 Link_Data frame */
-#define R_CTL_VIDEO 0x40 /* Video_Data frame */
-#define R_CTL_BASIC_SVC 0x80 /* Basic Link_Data frame */
-#define R_CTL_LINK_CTL 0xc0 /* Link_Control frame */
-/* FC4 Device_Data frames */
-#define R_CTL_UNCATEGORIZED 0x00
-#define R_CTL_SOLICITED_DATA 0x01
-#define R_CTL_UNSOL_CONTROL 0x02
-#define R_CTL_SOLICITED_CONTROL 0x03
-#define R_CTL_UNSOL_DATA 0x04
-#define R_CTL_XFER_RDY 0x05
-#define R_CTL_COMMAND 0x06
-#define R_CTL_STATUS 0x07
-/* Basic Link_Data frames */
-#define R_CTL_LS_NOP 0x80
-#define R_CTL_LS_ABTS 0x81
-#define R_CTL_LS_RMC 0x82
-#define R_CTL_LS_BA_ACC 0x84
-#define R_CTL_LS_BA_RJT 0x85
-/* Extended Link_Data frames */
-#define R_CTL_ELS_REQ 0x22
-#define R_CTL_ELS_RSP 0x23
-/* Link_Control frames */
-#define R_CTL_ACK_1 0xc0
-#define R_CTL_ACK_N 0xc1
-#define R_CTL_P_RJT 0xc2
-#define R_CTL_F_RJT 0xc3
-#define R_CTL_P_BSY 0xc4
-#define R_CTL_F_BSY_DF 0xc5
-#define R_CTL_F_BSY_LC 0xc6
-#define R_CTL_LCR 0xc7
-
-/* type field */
-#define TYPE_BASIC_LS 0x00
-#define TYPE_EXTENDED_LS 0x01
-#define TYPE_IS8802 0x04
-#define TYPE_IS8802_SNAP 0x05
-#define TYPE_SCSI_FCP 0x08
-#define TYPE_SCSI_GPP 0x09
-#define TYPE_HIPP_FP 0x0a
-#define TYPE_IPI3_MASTER 0x11
-#define TYPE_IPI3_SLAVE 0x12
-#define TYPE_IPI3_PEER 0x13
-
-/* f_ctl field */
-#define F_CTL_FILL_BYTES 0x000003
-#define F_CTL_XCHG_REASSEMBLE 0x000004
-#define F_CTL_RO_PRESENT 0x000008
-#define F_CTL_ABORT_SEQ 0x000030
-#define F_CTL_CONTINUE_SEQ 0x0000c0
-#define F_CTL_INVALIDATE_XID 0x004000
-#define F_CTL_XID_REASSIGNED 0x008000
-#define F_CTL_SEQ_INITIATIVE 0x010000
-#define F_CTL_CHAINED_SEQ 0x020000
-#define F_CTL_END_CONNECT 0x040000
-#define F_CTL_END_SEQ 0x080000
-#define F_CTL_LAST_SEQ 0x100000
-#define F_CTL_FIRST_SEQ 0x200000
-#define F_CTL_SEQ_CONTEXT 0x400000
-#define F_CTL_XCHG_CONTEXT 0x800000
-
-typedef struct {
- u32 r_ctl:8, did:24;
- u32 xxx1:8, sid:24;
- u32 type:8, f_ctl:24;
- u32 seq_id:8, df_ctl:8, seq_cnt:16;
- u16 ox_id, rx_id;
- u32 param;
-} fc_hdr;
-/* The following are ugly macros to make setup of this structure faster */
-#define FILL_FCHDR_RCTL_DID(fch, r_ctl, did) *(u32 *)(fch) = ((r_ctl) << 24) | (did);
-#define FILL_FCHDR_SID(fch, sid) *((u32 *)(fch)+1) = (sid);
-#define FILL_FCHDR_TYPE_FCTL(fch, type, f_ctl) *((u32 *)(fch)+2) = ((type) << 24) | (f_ctl);
-#define FILL_FCHDR_SEQ_DF_SEQ(fch, seq_id, df_ctl, seq_cnt) *((u32 *)(fch)+3) = ((seq_id) << 24) | ((df_ctl) << 16) | (seq_cnt);
-#define FILL_FCHDR_OXRX(fch, ox_id, rx_id) *((u32 *)(fch)+4) = ((ox_id) << 16) | (rx_id);
-
-/* Well known addresses */
-#define FS_GENERAL_MULTICAST 0xfffff7
-#define FS_WELL_KNOWN_MULTICAST 0xfffff8
-#define FS_HUNT_GROUP 0xfffff9
-#define FS_MANAGEMENT_SERVER 0xfffffa
-#define FS_TIME_SERVER 0xfffffb
-#define FS_NAME_SERVER 0xfffffc
-#define FS_FABRIC_CONTROLLER 0xfffffd
-#define FS_FABRIC_F_PORT 0xfffffe
-#define FS_BROADCAST 0xffffff
-
-/* Reject frames */
-/* The param field should be cast to this structure */
-typedef struct {
- u8 action;
- u8 reason;
- u8 xxx;
- u8 vendor_unique;
-} rjt_param;
-
-/* Reject action codes */
-#define RJT_RETRY 0x01
-#define RJT_NONRETRY 0x02
-
-/* Reject reason codes */
-#define RJT_INVALID_DID 0x01
-#define RJT_INVALID_SID 0x02
-#define RJT_NPORT_NOT_AVAIL_TEMP 0x03
-#define RJT_NPORT_NOT_AVAIL_PERM 0x04
-#define RJT_CLASS_NOT_SUPPORTED 0x05
-#define RJT_DELIMITER_ERROR 0x06
-#define RJT_TYPE_NOT_SUPPORTED 0x07
-#define RJT_INVALID_LINK_CONTROL 0x08
-#define RJT_INVALID_R_CTL 0x09
-#define RJT_INVALID_F_CTL 0x0a
-#define RJT_INVALID_OX_ID 0x0b
-#define RJT_INVALID_RX_ID 0x0c
-#define RJT_INVALID_SEQ_ID 0x0d
-#define RJT_INVALID_DF_CTL 0x0e
-#define RJT_INVALID_SEQ_CNT 0x0f
-#define RJT_INVALID_PARAMETER 0x10
-#define RJT_EXCHANGE_ERROR 0x11
-#define RJT_PROTOCOL_ERROR 0x12
-#define RJT_INCORRECT_LENGTH 0x13
-#define RJT_UNEXPECTED_ACK 0x14
-#define RJT_UNEXPECTED_LINK_RESP 0x15
-#define RJT_LOGIN_REQUIRED 0x16
-#define RJT_EXCESSIVE_SEQUENCES 0x17
-#define RJT_CANT_ESTABLISH_EXCHANGE 0x18
-#define RJT_SECURITY_NOT_SUPPORTED 0x19
-#define RJT_FABRIC_NA 0x1a
-#define RJT_VENDOR_UNIQUE 0xff
-
-
-#define SP_F_PORT_LOGIN 0x10
-
-/* Extended SVC commands */
-#define LS_RJT 0x01000000
-#define LS_ACC 0x02000000
-#define LS_PRLI_ACC 0x02100014
-#define LS_PLOGI 0x03000000
-#define LS_FLOGI 0x04000000
-#define LS_LOGO 0x05000000
-#define LS_ABTX 0x06000000
-#define LS_RCS 0x07000000
-#define LS_RES 0x08000000
-#define LS_RSS 0x09000000
-#define LS_RSI 0x0a000000
-#define LS_ESTS 0x0b000000
-#define LS_ESTC 0x0c000000
-#define LS_ADVC 0x0d000000
-#define LS_RTV 0x0e000000
-#define LS_RLS 0x0f000000
-#define LS_ECHO 0x10000000
-#define LS_TEST 0x11000000
-#define LS_RRQ 0x12000000
-#define LS_IDENT 0x20000000
-#define LS_PRLI 0x20100014
-#define LS_DISPLAY 0x21000000
-#define LS_PRLO 0x21100014
-#define LS_PDISC 0x50000000
-#define LS_ADISC 0x52000000
-
-typedef struct {
- u8 fcph_hi, fcph_lo;
- u16 buf2buf_credit;
- u8 common_features;
- u8 xxx1;
- u16 buf2buf_size;
- u8 xxx2;
- u8 total_concurrent;
- u16 off_by_info;
- u32 e_d_tov;
-} common_svc_parm;
-
-typedef struct {
- u16 serv_opts;
- u16 initiator_ctl;
- u16 rcpt_ctl;
- u16 recv_size;
- u8 xxx1;
- u8 concurrent_seqs;
- u16 end2end_credit;
- u16 open_seqs_per_xchg;
- u16 xxx2;
-} svc_parm;
-
-/* Login */
-typedef struct {
- u32 code;
- common_svc_parm common;
- fc_wwn nport_wwn;
- fc_wwn node_wwn;
- svc_parm class1;
- svc_parm class2;
- svc_parm class3;
-} logi;
-
-#endif /* !(__FC_H) */
diff --git a/drivers/fc4/fc_syms.c b/drivers/fc4/fc_syms.c
deleted file mode 100644
index bd3918ddf7a..00000000000
--- a/drivers/fc4/fc_syms.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * We should not even be trying to compile this if we are not doing
- * a module.
- */
-#include <linux/module.h>
-
-#ifdef CONFIG_MODULES
-
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#include "fcp_impl.h"
-
-EXPORT_SYMBOL(fcp_init);
-EXPORT_SYMBOL(fcp_release);
-EXPORT_SYMBOL(fcp_queue_empty);
-EXPORT_SYMBOL(fcp_receive_solicited);
-EXPORT_SYMBOL(fc_channels);
-EXPORT_SYMBOL(fcp_state_change);
-EXPORT_SYMBOL(fc_do_plogi);
-EXPORT_SYMBOL(fc_do_prli);
-
-/* SCSI stuff */
-EXPORT_SYMBOL(fcp_scsi_queuecommand);
-EXPORT_SYMBOL(fcp_scsi_abort);
-EXPORT_SYMBOL(fcp_scsi_dev_reset);
-EXPORT_SYMBOL(fcp_scsi_host_reset);
-
-#endif /* CONFIG_MODULES */
diff --git a/drivers/fc4/fcp.h b/drivers/fc4/fcp.h
deleted file mode 100644
index 6aa34a7a4c1..00000000000
--- a/drivers/fc4/fcp.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* fcp.h: Definitions for Fibre Channel Protocol.
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- */
-
-#ifndef __FCP_H
-#define __FCP_H
-
-/* FCP addressing is hierarchical with up to 4 layers, MS first.
- Exact meaning of the addresses is up to the vendor */
-
-/* fcp_cntl field */
-#define FCP_CNTL_WRITE 0x00000001 /* Initiator write */
-#define FCP_CNTL_READ 0x00000002 /* Initiator read */
-#define FCP_CNTL_ABORT_TSK 0x00000200 /* Abort task set */
-#define FCP_CNTL_CLR_TASK 0x00000400 /* Clear task set */
-#define FCP_CNTL_RESET 0x00002000 /* Reset */
-#define FCP_CNTL_CLR_ACA 0x00004000 /* Clear ACA */
-#define FCP_CNTL_KILL_TASK 0x00008000 /* Terminate task */
-#define FCP_CNTL_QTYPE_MASK 0x00070000 /* Tagged queueing type */
-#define FCP_CNTL_QTYPE_SIMPLE 0x00000000
-#define FCP_CNTL_QTYPE_HEAD_OF_Q 0x00010000
-#define FCP_CNTL_QTYPE_ORDERED 0x00020000
-#define FCP_CNTL_QTYPE_ACA_Q_TAG 0x00040000
-#define FCP_CNTL_QTYPE_UNTAGGED 0x00050000
-
-typedef struct {
- u16 fcp_addr[4];
- u32 fcp_cntl;
- u8 fcp_cdb[16];
- u32 fcp_data_len;
-} fcp_cmd;
-
-/* fcp_status field */
-#define FCP_STATUS_MASK 0x000000ff /* scsi status of command */
-#define FCP_STATUS_RSP_LEN 0x00000100 /* response_len != 0 */
-#define FCP_STATUS_SENSE_LEN 0x00000200 /* sense_len != 0 */
-#define FCP_STATUS_RESID 0x00000400 /* resid != 0 */
-
-typedef struct {
- u32 xxx[2];
- u32 fcp_status;
- u32 fcp_resid;
- u32 fcp_sense_len;
- u32 fcp_response_len;
- /* u8 fcp_sense[fcp_sense_len]; */
- /* u8 fcp_response[fcp_response_len]; */
-} fcp_rsp;
-
-/* fcp errors */
-
-/* rsp_info_type field */
-#define FCP_RSP_SCSI_BUS_ERR 0x01
-#define FCP_RSP_SCSI_PORT_ERR 0x02
-#define FCP_RSP_CARD_ERR 0x03
-
-/* isp_status field */
-#define FCP_RSP_CMD_COMPLETE 0x0000
-#define FCP_RSP_CMD_INCOMPLETE 0x0001
-#define FCP_RSP_CMD_DMA_ERR 0x0002
-#define FCP_RSP_CMD_TRAN_ERR 0x0003
-#define FCP_RSP_CMD_RESET 0x0004
-#define FCP_RSP_CMD_ABORTED 0x0005
-#define FCP_RSP_CMD_TIMEOUT 0x0006
-#define FCP_RSP_CMD_OVERRUN 0x0007
-
-/* isp_state_flags field */
-#define FCP_RSP_ST_GOT_BUS 0x0100
-#define FCP_RSP_ST_GOT_TARGET 0x0200
-#define FCP_RSP_ST_SENT_CMD 0x0400
-#define FCP_RSP_ST_XFRD_DATA 0x0800
-#define FCP_RSP_ST_GOT_STATUS 0x1000
-#define FCP_RSP_ST_GOT_SENSE 0x2000
-
-/* isp_stat_flags field */
-#define FCP_RSP_STAT_DISC 0x0001
-#define FCP_RSP_STAT_SYNC 0x0002
-#define FCP_RSP_STAT_PERR 0x0004
-#define FCP_RSP_STAT_BUS_RESET 0x0008
-#define FCP_RSP_STAT_DEV_RESET 0x0010
-#define FCP_RSP_STAT_ABORTED 0x0020
-#define FCP_RSP_STAT_TIMEOUT 0x0040
-#define FCP_RSP_STAT_NEGOTIATE 0x0080
-
-typedef struct {
- u8 rsp_info_type;
- u8 xxx;
- u16 isp_status;
- u16 isp_state_flags;
- u16 isp_stat_flags;
-} fcp_scsi_err;
-
-#endif /* !(__FCP_H) */
diff --git a/drivers/fc4/fcp_impl.h b/drivers/fc4/fcp_impl.h
deleted file mode 100644
index 506338a461b..00000000000
--- a/drivers/fc4/fcp_impl.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* fcp_impl.h: Generic SCSI on top of FC4 - our interface defines.
- *
- * Copyright (C) 1997-1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Jirka Hanika (geo@ff.cuni.cz)
- */
-
-#ifndef _FCP_SCSI_H
-#define _FCP_SCSI_H
-
-#include <linux/types.h>
-#include "../scsi/scsi.h"
-
-#include "fc.h"
-#include "fcp.h"
-#include "fc-al.h"
-
-#include <asm/io.h>
-#ifdef __sparc__
-#include <asm/sbus.h>
-#endif
-
-/* 0 or 1 */
-#define FCP_SCSI_USE_NEW_EH_CODE 0
-
-#define FC_CLASS_OUTBOUND 0x01
-#define FC_CLASS_INBOUND 0x02
-#define FC_CLASS_SIMPLE 0x03
-#define FC_CLASS_IO_WRITE 0x04
-#define FC_CLASS_IO_READ 0x05
-#define FC_CLASS_UNSOLICITED 0x06
-#define FC_CLASS_OFFLINE 0x08
-
-#define PROTO_OFFLINE 0x02
-#define PROTO_REPORT_AL_MAP 0x03
-#define PROTO_FORCE_LIP 0x06
-
-struct _fc_channel;
-
-typedef struct fcp_cmnd {
- struct fcp_cmnd *next;
- struct fcp_cmnd *prev;
- void (*done)(struct scsi_cmnd *);
- unsigned short proto;
- unsigned short token;
- unsigned int did;
- /* FCP SCSI stuff */
- dma_addr_t data;
- /* From now on this cannot be touched for proto == TYPE_SCSI_FCP */
- fc_hdr fch;
- dma_addr_t cmd;
- dma_addr_t rsp;
- int cmdlen;
- int rsplen;
- int class;
- int datalen;
- /* This is just used as a verification during login */
- struct _fc_channel *fc;
- void *ls;
-} fcp_cmnd;
-
-typedef struct {
- unsigned int len;
- unsigned char list[0];
-} fcp_posmap;
-
-typedef struct _fc_channel {
- struct _fc_channel *next;
- int irq;
- int state;
- int sid;
- int did;
- char name[16];
- void (*fcp_register)(struct _fc_channel *, u8, int);
- void (*reset)(struct _fc_channel *);
- int (*hw_enque)(struct _fc_channel *, fcp_cmnd *);
- fc_wwn wwn_node;
- fc_wwn wwn_nport;
- fc_wwn wwn_dest;
- common_svc_parm *common_svc;
- svc_parm *class_svcs;
-#ifdef __sparc__
- struct sbus_dev *dev;
-#else
- struct pci_dev *dev;
-#endif
- struct module *module;
- /* FCP SCSI stuff */
- short can_queue;
- short abort_count;
- int rsp_size;
- fcp_cmd *scsi_cmd_pool;
- char *scsi_rsp_pool;
- dma_addr_t dma_scsi_cmd, dma_scsi_rsp;
- unsigned long *scsi_bitmap;
- long scsi_bitmap_end;
- int scsi_free;
- int (*encode_addr)(struct scsi_cmnd *, u16 *, struct _fc_channel *, fcp_cmnd *);
- fcp_cmnd *scsi_que;
- char scsi_name[4];
- fcp_cmnd **cmd_slots;
- int channels;
- int targets;
- long *ages;
- struct scsi_cmnd *rst_pkt;
- fcp_posmap *posmap;
- /* LOGIN stuff */
- fcp_cmnd *login;
- void *ls;
-} fc_channel;
-
-extern fc_channel *fc_channels;
-
-#define FC_STATE_UNINITED 0
-#define FC_STATE_ONLINE 1
-#define FC_STATE_OFFLINE 2
-#define FC_STATE_RESETING 3
-#define FC_STATE_FPORT_OK 4
-#define FC_STATE_MAYBEOFFLINE 5
-
-#define FC_STATUS_OK 0
-#define FC_STATUS_P_RJT 2
-#define FC_STATUS_F_RJT 3
-#define FC_STATUS_P_BSY 4
-#define FC_STATUS_F_BSY 5
-#define FC_STATUS_ERR_OFFLINE 0x11
-#define FC_STATUS_TIMEOUT 0x12
-#define FC_STATUS_ERR_OVERRUN 0x13
-#define FC_STATUS_POINTTOPOINT 0x15
-#define FC_STATUS_AL 0x16
-#define FC_STATUS_UNKNOWN_CQ_TYPE 0x20
-#define FC_STATUS_BAD_SEG_CNT 0x21
-#define FC_STATUS_MAX_XCHG_EXCEEDED 0x22
-#define FC_STATUS_BAD_XID 0x23
-#define FC_STATUS_XCHG_BUSY 0x24
-#define FC_STATUS_BAD_POOL_ID 0x25
-#define FC_STATUS_INSUFFICIENT_CQES 0x26
-#define FC_STATUS_ALLOC_FAIL 0x27
-#define FC_STATUS_BAD_SID 0x28
-#define FC_STATUS_NO_SEQ_INIT 0x29
-#define FC_STATUS_TIMED_OUT -1
-#define FC_STATUS_BAD_RSP -2
-
-void fcp_queue_empty(fc_channel *);
-int fcp_init(fc_channel *);
-void fcp_release(fc_channel *fc_chain, int count);
-void fcp_receive_solicited(fc_channel *, int, int, int, fc_hdr *);
-void fcp_state_change(fc_channel *, int);
-int fc_do_plogi(fc_channel *, unsigned char, fc_wwn *, fc_wwn *);
-int fc_do_prli(fc_channel *, unsigned char);
-
-#define for_each_fc_channel(fc) \
- for (fc = fc_channels; fc; fc = fc->next)
-
-#define for_each_online_fc_channel(fc) \
- for_each_fc_channel(fc) \
- if (fc->state == FC_STATE_ONLINE)
-
-int fcp_scsi_queuecommand(struct scsi_cmnd *,
- void (* done) (struct scsi_cmnd *));
-int fcp_scsi_abort(struct scsi_cmnd *);
-int fcp_scsi_dev_reset(struct scsi_cmnd *);
-int fcp_scsi_host_reset(struct scsi_cmnd *);
-
-#endif /* !(_FCP_SCSI_H) */
diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c
deleted file mode 100644
index d517734462e..00000000000
--- a/drivers/fc4/soc.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/* soc.c: Sparc SUNW,soc (Serial Optical Channel) Fibre Channel Sbus adapter support.
- *
- * Copyright (C) 1996,1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
- *
- * Sources:
- * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
- * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
- *
- * Supported hardware:
- * Tested on SOC sbus card bought with SS1000 in Linux running on SS5 and Ultra1.
- * For SOC sbus cards, you have to make sure your FCode is 1.52 or later.
- * If you have older FCode, you should try to upgrade or get SOC microcode from Sun
- * (the microcode is present in Solaris soc driver as well). In that case you need
- * to #define HAVE_SOC_UCODE and format the microcode into soc_asm.c. For the exact
- * format mail me and I will tell you. I cannot offer you the actual microcode though,
- * unless Sun confirms they don't mind.
- */
-
-static char *version =
- "soc.c:v1.3 9/Feb/99 Jakub Jelinek (jj@ultra.linux.cz), Jirka Hanika (geo@ff.cuni.cz)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/errno.h>
-#include <asm/byteorder.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-
-/* #define SOCDEBUG */
-/* #define HAVE_SOC_UCODE */
-
-#include "fcp_impl.h"
-#include "soc.h"
-#ifdef HAVE_SOC_UCODE
-#include "soc_asm.h"
-#endif
-
-#define soc_printk printk ("soc%d: ", s->soc_no); printk
-
-#ifdef SOCDEBUG
-#define SOD(x) soc_printk x;
-#else
-#define SOD(x)
-#endif
-
-#define for_each_soc(s) for (s = socs; s; s = s->next)
-struct soc *socs = NULL;
-
-static inline void soc_disable(struct soc *s)
-{
- sbus_writel(0, s->regs + IMASK);
- sbus_writel(SOC_CMD_SOFT_RESET, s->regs + CMD);
-}
-
-static inline void soc_enable(struct soc *s)
-{
- SOD(("enable %08x\n", s->cfg))
- sbus_writel(0, s->regs + SAE);
- sbus_writel(s->cfg, s->regs + CFG);
- sbus_writel(SOC_CMD_RSP_QALL, s->regs + CMD);
- SOC_SETIMASK(s, SOC_IMASK_RSP_QALL | SOC_IMASK_SAE);
- SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMAK)));
-}
-
-static void soc_reset(fc_channel *fc)
-{
- soc_port *port = (soc_port *)fc;
- struct soc *s = port->s;
-
- /* FIXME */
- soc_disable(s);
- s->req[0].seqno = 1;
- s->req[1].seqno = 1;
- s->rsp[0].seqno = 1;
- s->rsp[1].seqno = 1;
- s->req[0].in = 0;
- s->req[1].in = 0;
- s->rsp[0].in = 0;
- s->rsp[1].in = 0;
- s->req[0].out = 0;
- s->req[1].out = 0;
- s->rsp[0].out = 0;
- s->rsp[1].out = 0;
-
- /* FIXME */
- soc_enable(s);
-}
-
-static inline void soc_solicited (struct soc *s)
-{
- fc_hdr fchdr;
- soc_rsp __iomem *hwrsp;
- soc_cq_rsp *sw_cq;
- int token;
- int status;
- fc_channel *fc;
-
- sw_cq = &s->rsp[SOC_SOLICITED_RSP_Q];
-
- if (sw_cq->pool == NULL)
- sw_cq->pool = (soc_req __iomem *)
- (s->xram + xram_get_32low ((xram_p)&sw_cq->hw_cq->address));
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- SOD (("soc_solicited, %d pkts arrived\n", (sw_cq->in-sw_cq->out) & sw_cq->last))
- for (;;) {
- hwrsp = (soc_rsp __iomem *)sw_cq->pool + sw_cq->out;
- token = xram_get_32low ((xram_p)&hwrsp->shdr.token);
- status = xram_get_32low ((xram_p)&hwrsp->status);
- fc = (fc_channel *)(&s->port[(token >> 11) & 1]);
-
- if (status == SOC_OK) {
- fcp_receive_solicited(fc, token >> 12,
- token & ((1 << 11) - 1),
- FC_STATUS_OK, NULL);
- } else {
- xram_copy_from(&fchdr, (xram_p)&hwrsp->fchdr, sizeof(fchdr));
- /* We have intentionally defined FC_STATUS_* constants
- * to match SOC_* constants, otherwise we'd have to
- * translate status.
- */
- fcp_receive_solicited(fc, token >> 12,
- token & ((1 << 11) - 1),
- status, &fchdr);
- }
-
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
-
- if (sw_cq->out == sw_cq->in) {
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- if (sw_cq->out == sw_cq->in) {
- /* Tell the hardware about it */
- sbus_writel((sw_cq->out << 24) |
- (SOC_CMD_RSP_QALL &
- ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- if (sw_cq->out == sw_cq->in)
- break;
- }
- }
- }
-}
-
-static inline void soc_request (struct soc *s, u32 cmd)
-{
- SOC_SETIMASK(s, s->imask & ~(cmd & SOC_CMD_REQ_QALL));
- SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK)));
-
- SOD(("Queues available %08x OUT %X %X\n", cmd,
- xram_get_8((xram_p)&s->req[0].hw_cq->out),
- xram_get_8((xram_p)&s->req[0].hw_cq->out)))
- if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) {
- fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port]));
- if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out))
- fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
- } else {
- fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
- }
- if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE)
- s->curr_port ^= 1;
-}
-
-static inline void soc_unsolicited (struct soc *s)
-{
- soc_rsp __iomem *hwrsp, *hwrspc;
- soc_cq_rsp *sw_cq;
- int count;
- int status;
- int flags;
- fc_channel *fc;
-
- sw_cq = &s->rsp[SOC_UNSOLICITED_RSP_Q];
- if (sw_cq->pool == NULL)
- sw_cq->pool = (soc_req __iomem *)
- (s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address)));
-
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- SOD (("soc_unsolicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last))
- while (sw_cq->in != sw_cq->out) {
- /* ...real work per entry here... */
- hwrsp = (soc_rsp __iomem *)sw_cq->pool + sw_cq->out;
-
- hwrspc = NULL;
- flags = xram_get_16 ((xram_p)&hwrsp->shdr.flags);
- count = xram_get_8 ((xram_p)&hwrsp->count);
- fc = (fc_channel *)&s->port[flags & SOC_PORT_B];
- SOD(("FC %08lx fcp_state_change %08lx\n",
- (long)fc, (long)fc->fcp_state_change))
-
- if (count != 1) {
- /* Ugh, continuation entries */
- u8 in;
-
- if (count != 2) {
- printk("%s: Too many continuations entries %d\n",
- fc->name, count);
- goto update_out;
- }
-
- in = sw_cq->in;
- if (in < sw_cq->out) in += sw_cq->last + 1;
- if (in < sw_cq->out + 2) {
- /* Ask the hardware if they haven't arrived yet. */
- sbus_writel((sw_cq->out << 24) |
- (SOC_CMD_RSP_QALL &
- ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- in = sw_cq->in;
- if (in < sw_cq->out)
- in += sw_cq->last + 1;
- if (in < sw_cq->out + 2) /* Nothing came, let us wait */
- return;
- }
- if (sw_cq->out == sw_cq->last)
- hwrspc = (soc_rsp __iomem *)sw_cq->pool;
- else
- hwrspc = hwrsp + 1;
- }
-
- switch (flags & ~SOC_PORT_B) {
- case SOC_STATUS:
- status = xram_get_32low ((xram_p)&hwrsp->status);
- switch (status) {
- case SOC_ONLINE:
- SOD(("State change to ONLINE\n"));
- fcp_state_change(fc, FC_STATE_ONLINE);
- break;
- case SOC_OFFLINE:
- SOD(("State change to OFFLINE\n"));
- fcp_state_change(fc, FC_STATE_OFFLINE);
- break;
- default:
- printk ("%s: Unknown STATUS no %d\n",
- fc->name, status);
- break;
- }
- break;
- case (SOC_UNSOLICITED|SOC_FC_HDR):
- {
- int r_ctl = xram_get_8 ((xram_p)&hwrsp->fchdr);
- unsigned len;
- char buf[64];
-
- if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) {
- len = xram_get_32 ((xram_p)&hwrsp->shdr.bytecnt);
- if (len < 4 || !hwrspc) {
- printk ("%s: Invalid R_CTL %02x "
- "continuation entries\n",
- fc->name, r_ctl);
- } else {
- if (len > 60)
- len = 60;
- xram_copy_from (buf, (xram_p)hwrspc,
- (len + 3) & ~3);
- if (*(u32 *)buf == LS_DISPLAY) {
- int i;
-
- for (i = 4; i < len; i++)
- if (buf[i] == '\n')
- buf[i] = ' ';
- buf[len] = 0;
- printk ("%s message: %s\n",
- fc->name, buf + 4);
- } else {
- printk ("%s: Unknown LS_CMD "
- "%02x\n", fc->name,
- buf[0]);
- }
- }
- } else {
- printk ("%s: Unsolicited R_CTL %02x "
- "not handled\n", fc->name, r_ctl);
- }
- }
- break;
- default:
- printk ("%s: Unexpected flags %08x\n", fc->name, flags);
- break;
- };
-update_out:
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
-
- if (hwrspc) {
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
- }
-
- if (sw_cq->out == sw_cq->in) {
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- if (sw_cq->out == sw_cq->in) {
- /* Tell the hardware about it */
- sbus_writel((sw_cq->out << 24) |
- (SOC_CMD_RSP_QALL &
- ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
- }
- }
- }
-}
-
-static irqreturn_t soc_intr(int irq, void *dev_id)
-{
- u32 cmd;
- unsigned long flags;
- register struct soc *s = (struct soc *)dev_id;
-
- spin_lock_irqsave(&s->lock, flags);
- cmd = sbus_readl(s->regs + CMD);
- for (; (cmd = SOC_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) {
- if (cmd & SOC_CMD_RSP_Q1) soc_unsolicited (s);
- if (cmd & SOC_CMD_RSP_Q0) soc_solicited (s);
- if (cmd & SOC_CMD_REQ_QALL) soc_request (s, cmd);
- }
- spin_unlock_irqrestore(&s->lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#define TOKEN(proto, port, token) (((proto)<<12)|(token)|(port))
-
-static int soc_hw_enque (fc_channel *fc, fcp_cmnd *fcmd)
-{
- soc_port *port = (soc_port *)fc;
- struct soc *s = port->s;
- int qno;
- soc_cq_req *sw_cq;
- int cq_next_in;
- soc_req *request;
- fc_hdr *fch;
- int i;
-
- if (fcmd->proto == TYPE_SCSI_FCP)
- qno = 1;
- else
- qno = 0;
- SOD(("Putting a FCP packet type %d into hw queue %d\n", fcmd->proto, qno))
- if (s->imask & (SOC_IMASK_REQ_Q0 << qno)) {
- SOD(("EIO %08x\n", s->imask))
- return -EIO;
- }
- sw_cq = s->req + qno;
- cq_next_in = (sw_cq->in + 1) & sw_cq->last;
-
- if (cq_next_in == sw_cq->out &&
- cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) {
- SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last))
- SOC_SETIMASK(s, s->imask | (SOC_IMASK_REQ_Q0 << qno));
- SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK)));
- /* If queue is full, just say NO */
- return -EBUSY;
- }
-
- request = sw_cq->pool + sw_cq->in;
- fch = &request->fchdr;
-
- switch (fcmd->proto) {
- case TYPE_SCSI_FCP:
- request->shdr.token = TOKEN(TYPE_SCSI_FCP, port->mask, fcmd->token);
- request->data[0].base = fc->dma_scsi_cmd + fcmd->token * sizeof(fcp_cmd);
- request->data[0].count = sizeof(fcp_cmd);
- request->data[1].base = fc->dma_scsi_rsp + fcmd->token * fc->rsp_size;
- request->data[1].count = fc->rsp_size;
- if (fcmd->data) {
- request->shdr.segcnt = 3;
- i = fc->scsi_cmd_pool[fcmd->token].fcp_data_len;
- request->shdr.bytecnt = i;
- request->data[2].base = fcmd->data;
- request->data[2].count = i;
- request->type =
- (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ?
- SOC_CQTYPE_IO_WRITE : SOC_CQTYPE_IO_READ;
- } else {
- request->shdr.segcnt = 2;
- request->shdr.bytecnt = 0;
- request->data[2].base = 0;
- request->data[2].count = 0;
- request->type = SOC_CQTYPE_SIMPLE;
- }
- FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP,
- F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- request->shdr.flags = port->flags;
- request->shdr.class = 2;
- break;
-
- case PROTO_OFFLINE:
- memset (request, 0, sizeof(*request));
- request->shdr.token = TOKEN(PROTO_OFFLINE, port->mask, fcmd->token);
- request->type = SOC_CQTYPE_OFFLINE;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP,
- F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- request->shdr.flags = port->flags;
- break;
-
- case PROTO_REPORT_AL_MAP:
- /* SOC only supports Point-to-Point topology, no FC-AL, sorry... */
- return -ENOSYS;
-
- default:
- request->shdr.token = TOKEN(fcmd->proto, port->mask, fcmd->token);
- request->shdr.class = 2;
- request->shdr.flags = port->flags;
- memcpy (fch, &fcmd->fch, sizeof(fc_hdr));
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = fcmd->class;
- switch (fcmd->class) {
- case FC_CLASS_OUTBOUND:
- request->data[0].base = fcmd->cmd;
- request->data[0].count = fcmd->cmdlen;
- request->type = SOC_CQTYPE_OUTBOUND;
- request->shdr.bytecnt = fcmd->cmdlen;
- request->shdr.segcnt = 1;
- break;
- case FC_CLASS_INBOUND:
- request->data[0].base = fcmd->rsp;
- request->data[0].count = fcmd->rsplen;
- request->type = SOC_CQTYPE_INBOUND;
- request->shdr.bytecnt = 0;
- request->shdr.segcnt = 1;
- break;
- case FC_CLASS_SIMPLE:
- request->data[0].base = fcmd->cmd;
- request->data[1].base = fcmd->rsp;
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = SOC_CQTYPE_SIMPLE;
- request->shdr.bytecnt = fcmd->cmdlen;
- request->shdr.segcnt = 2;
- break;
- case FC_CLASS_IO_READ:
- case FC_CLASS_IO_WRITE:
- request->data[0].base = fcmd->cmd;
- request->data[1].base = fcmd->rsp;
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type =
- (fcmd->class == FC_CLASS_IO_READ) ?
- SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE;
- if (fcmd->data) {
- request->data[2].base = fcmd->data;
- request->data[2].count = fcmd->datalen;
- request->shdr.bytecnt = fcmd->datalen;
- request->shdr.segcnt = 3;
- } else {
- request->shdr.bytecnt = 0;
- request->shdr.segcnt = 2;
- }
- break;
- };
- break;
- };
-
- request->count = 1;
- request->flags = 0;
- request->seqno = sw_cq->seqno;
-
- /* And now tell the SOC about it */
-
- if (++sw_cq->in > sw_cq->last) {
- sw_cq->in = 0;
- sw_cq->seqno++;
- }
-
- SOD(("Putting %08x into cmd\n",
- SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno)))
-
- sbus_writel(SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno),
- s->regs + CMD);
-
- /* Read so that command is completed. */
- sbus_readl(s->regs + CMD);
-
- return 0;
-}
-
-static inline void soc_download_fw(struct soc *s)
-{
-#ifdef HAVE_SOC_UCODE
- xram_copy_to (s->xram, soc_ucode, sizeof(soc_ucode));
- xram_bzero (s->xram + sizeof(soc_ucode), 32768 - sizeof(soc_ucode));
-#endif
-}
-
-/* Check for what the best SBUS burst we can use happens
- * to be on this machine.
- */
-static inline void soc_init_bursts(struct soc *s, struct sbus_dev *sdev)
-{
- int bsizes, bsizes_more;
-
- bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff);
- bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff);
- bsizes &= bsizes_more;
- if ((bsizes & 0x7f) == 0x7f)
- s->cfg = SOC_CFG_BURST_64;
- else if ((bsizes & 0x3f) == 0x3f)
- s->cfg = SOC_CFG_BURST_32;
- else if ((bsizes & 0x1f) == 0x1f)
- s->cfg = SOC_CFG_BURST_16;
- else
- s->cfg = SOC_CFG_BURST_4;
-}
-
-static inline void soc_init(struct sbus_dev *sdev, int no)
-{
- unsigned char tmp[60];
- int propl;
- struct soc *s;
- static int version_printed = 0;
- soc_hw_cq cq[8];
- int size, i;
- int irq;
-
- s = kzalloc (sizeof (struct soc), GFP_KERNEL);
- if (s == NULL)
- return;
- spin_lock_init(&s->lock);
- s->soc_no = no;
-
- SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n",
- (long)socs, (long)soc_intr, (long)soc_hw_enque))
- if (version_printed++ == 0)
- printk (version);
-
- s->port[0].fc.module = THIS_MODULE;
- s->port[1].fc.module = THIS_MODULE;
-
- s->next = socs;
- socs = s;
- s->port[0].fc.dev = sdev;
- s->port[1].fc.dev = sdev;
- s->port[0].s = s;
- s->port[1].s = s;
-
- s->port[0].fc.next = &s->port[1].fc;
-
- /* World Wide Name of SOC */
- propl = prom_getproperty (sdev->prom_node, "soc-wwn", tmp, sizeof(tmp));
- if (propl != sizeof (fc_wwn)) {
- s->wwn.naaid = NAAID_IEEE;
- s->wwn.lo = 0x12345678;
- } else
- memcpy (&s->wwn, tmp, sizeof (fc_wwn));
-
- propl = prom_getproperty (sdev->prom_node, "port-wwns", tmp, sizeof(tmp));
- if (propl != 2 * sizeof (fc_wwn)) {
- s->port[0].fc.wwn_nport.naaid = NAAID_IEEE_EXT;
- s->port[0].fc.wwn_nport.hi = s->wwn.hi;
- s->port[0].fc.wwn_nport.lo = s->wwn.lo;
- s->port[1].fc.wwn_nport.naaid = NAAID_IEEE_EXT;
- s->port[1].fc.wwn_nport.nportid = 1;
- s->port[1].fc.wwn_nport.hi = s->wwn.hi;
- s->port[1].fc.wwn_nport.lo = s->wwn.lo;
- } else {
- memcpy (&s->port[0].fc.wwn_nport, tmp, sizeof (fc_wwn));
- memcpy (&s->port[1].fc.wwn_nport, tmp + sizeof (fc_wwn), sizeof (fc_wwn));
- }
- memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
- memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
- SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n",
- *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
- *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
- *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
-
- s->port[0].fc.sid = 1;
- s->port[1].fc.sid = 17;
- s->port[0].fc.did = 2;
- s->port[1].fc.did = 18;
-
- s->port[0].fc.reset = soc_reset;
- s->port[1].fc.reset = soc_reset;
-
- if (sdev->num_registers == 1) {
- /* Probably SunFire onboard SOC */
- s->xram = sbus_ioremap(&sdev->resource[0], 0,
- 0x10000UL, "soc xram");
- s->regs = sbus_ioremap(&sdev->resource[0], 0x10000UL,
- 0x10UL, "soc regs");
- } else {
- /* Probably SOC sbus card */
- s->xram = sbus_ioremap(&sdev->resource[1], 0,
- sdev->reg_addrs[1].reg_size, "soc xram");
- s->regs = sbus_ioremap(&sdev->resource[2], 0,
- sdev->reg_addrs[2].reg_size, "soc regs");
- }
-
- soc_init_bursts(s, sdev);
-
- SOD(("Disabling SOC\n"))
-
- soc_disable (s);
-
- irq = sdev->irqs[0];
-
- if (request_irq (irq, soc_intr, IRQF_SHARED, "SOC", (void *)s)) {
- soc_printk ("Cannot order irq %d to go\n", irq);
- socs = s->next;
- return;
- }
-
- SOD(("SOC uses IRQ %d\n", irq))
-
- s->port[0].fc.irq = irq;
- s->port[1].fc.irq = irq;
-
- sprintf (s->port[0].fc.name, "soc%d port A", no);
- sprintf (s->port[1].fc.name, "soc%d port B", no);
- s->port[0].flags = SOC_FC_HDR | SOC_PORT_A;
- s->port[1].flags = SOC_FC_HDR | SOC_PORT_B;
- s->port[1].mask = (1 << 11);
-
- s->port[0].fc.hw_enque = soc_hw_enque;
- s->port[1].fc.hw_enque = soc_hw_enque;
-
- soc_download_fw (s);
-
- SOD(("Downloaded firmware\n"))
-
- /* Now setup xram circular queues */
- memset (cq, 0, sizeof(cq));
-
- size = (SOC_CQ_REQ0_SIZE + SOC_CQ_REQ1_SIZE) * sizeof(soc_req);
- s->req_cpu = sbus_alloc_consistent(sdev, size, &s->req_dvma);
- s->req[0].pool = s->req_cpu;
- cq[0].address = s->req_dvma;
- s->req[1].pool = s->req[0].pool + SOC_CQ_REQ0_SIZE;
-
- s->req[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET);
- s->req[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq));
- s->rsp[0].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET);
- s->rsp[1].hw_cq = (soc_hw_cq __iomem *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq));
-
- cq[1].address = cq[0].address + (SOC_CQ_REQ0_SIZE * sizeof(soc_req));
- cq[4].address = 1;
- cq[5].address = 1;
- cq[0].last = SOC_CQ_REQ0_SIZE - 1;
- cq[1].last = SOC_CQ_REQ1_SIZE - 1;
- cq[4].last = SOC_CQ_RSP0_SIZE - 1;
- cq[5].last = SOC_CQ_RSP1_SIZE - 1;
- for (i = 0; i < 8; i++)
- cq[i].seqno = 1;
-
- s->req[0].last = SOC_CQ_REQ0_SIZE - 1;
- s->req[1].last = SOC_CQ_REQ1_SIZE - 1;
- s->rsp[0].last = SOC_CQ_RSP0_SIZE - 1;
- s->rsp[1].last = SOC_CQ_RSP1_SIZE - 1;
-
- s->req[0].seqno = 1;
- s->req[1].seqno = 1;
- s->rsp[0].seqno = 1;
- s->rsp[1].seqno = 1;
-
- xram_copy_to (s->xram + SOC_CQ_REQ_OFFSET, cq, sizeof(cq));
-
- /* Make our sw copy of SOC service parameters */
- xram_copy_from (s->serv_params, s->xram + 0x140, sizeof (s->serv_params));
-
- s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params;
- s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
- s->port[1].fc.common_svc = (common_svc_parm *)&s->serv_params;
- s->port[1].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
-
- soc_enable (s);
-
- SOD(("Enabled SOC\n"))
-}
-
-static int __init soc_probe(void)
-{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev = NULL;
- struct soc *s;
- int cards = 0;
-
- for_each_sbus(sbus) {
- for_each_sbusdev(sdev, sbus) {
- if(!strcmp(sdev->prom_name, "SUNW,soc")) {
- soc_init(sdev, cards);
- cards++;
- }
- }
- }
- if (!cards) return -EIO;
-
- for_each_soc(s)
- if (s->next)
- s->port[1].fc.next = &s->next->port[0].fc;
- fcp_init (&socs->port[0].fc);
- return 0;
-}
-
-static void __exit soc_cleanup(void)
-{
- struct soc *s;
- int irq;
- struct sbus_dev *sdev;
-
- for_each_soc(s) {
- irq = s->port[0].fc.irq;
- free_irq (irq, s);
-
- fcp_release(&(s->port[0].fc), 2);
-
- sdev = s->port[0].fc.dev;
- if (sdev->num_registers == 1) {
- sbus_iounmap(s->xram, 0x10000UL);
- sbus_iounmap(s->regs, 0x10UL);
- } else {
- sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size);
- sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size);
- }
- sbus_free_consistent(sdev,
- (SOC_CQ_REQ0_SIZE+SOC_CQ_REQ1_SIZE)*sizeof(soc_req),
- s->req_cpu, s->req_dvma);
- }
-}
-
-module_init(soc_probe);
-module_exit(soc_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/fc4/soc.h b/drivers/fc4/soc.h
deleted file mode 100644
index d38cf5b28ee..00000000000
--- a/drivers/fc4/soc.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/* soc.h: Definitions for Sparc SUNW,soc Fibre Channel Sbus driver.
- *
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#ifndef __SOC_H
-#define __SOC_H
-
-#include "fc.h"
-#include "fcp.h"
-#include "fcp_impl.h"
-
-/* Hardware register offsets and constants first {{{ */
-#define CFG 0x00UL /* Config Register */
-#define SAE 0x04UL /* Slave Access Error Register */
-#define CMD 0x08UL /* Command and Status Register */
-#define IMASK 0x0cUL /* Interrupt Mask Register */
-
-/* Config Register */
-#define SOC_CFG_EXT_RAM_BANK_MASK 0x07000000
-#define SOC_CFG_EEPROM_BANK_MASK 0x00030000
-#define SOC_CFG_BURST64_MASK 0x00000700
-#define SOC_CFG_SBUS_PARITY_TEST 0x00000020
-#define SOC_CFG_SBUS_PARITY_CHECK 0x00000010
-#define SOC_CFG_SBUS_ENHANCED 0x00000008
-#define SOC_CFG_BURST_MASK 0x00000007
-/* Bursts */
-#define SOC_CFG_BURST_4 0x00000000
-#define SOC_CFG_BURST_16 0x00000004
-#define SOC_CFG_BURST_32 0x00000005
-#define SOC_CFG_BURST_64 0x00000006
-
-/* Slave Access Error Register */
-#define SOC_SAE_ALIGNMENT 0x00000004
-#define SOC_SAE_UNSUPPORTED 0x00000002
-#define SOC_SAE_PARITY 0x00000001
-
-/* Command & Status Register */
-#define SOC_CMD_RSP_QALL 0x000f0000
-#define SOC_CMD_RSP_Q0 0x00010000
-#define SOC_CMD_RSP_Q1 0x00020000
-#define SOC_CMD_RSP_Q2 0x00040000
-#define SOC_CMD_RSP_Q3 0x00080000
-#define SOC_CMD_REQ_QALL 0x00000f00
-#define SOC_CMD_REQ_Q0 0x00000100
-#define SOC_CMD_REQ_Q1 0x00000200
-#define SOC_CMD_REQ_Q2 0x00000400
-#define SOC_CMD_REQ_Q3 0x00000800
-#define SOC_CMD_SAE 0x00000080
-#define SOC_CMD_INTR_PENDING 0x00000008
-#define SOC_CMD_NON_QUEUED 0x00000004
-#define SOC_CMD_IDLE 0x00000002
-#define SOC_CMD_SOFT_RESET 0x00000001
-
-/* Interrupt Mask Register */
-#define SOC_IMASK_RSP_QALL 0x000f0000
-#define SOC_IMASK_RSP_Q0 0x00010000
-#define SOC_IMASK_RSP_Q1 0x00020000
-#define SOC_IMASK_RSP_Q2 0x00040000
-#define SOC_IMASK_RSP_Q3 0x00080000
-#define SOC_IMASK_REQ_QALL 0x00000f00
-#define SOC_IMASK_REQ_Q0 0x00000100
-#define SOC_IMASK_REQ_Q1 0x00000200
-#define SOC_IMASK_REQ_Q2 0x00000400
-#define SOC_IMASK_REQ_Q3 0x00000800
-#define SOC_IMASK_SAE 0x00000080
-#define SOC_IMASK_NON_QUEUED 0x00000004
-
-#define SOC_INTR(s, cmd) \
- (((cmd & SOC_CMD_RSP_QALL) | ((~cmd) & SOC_CMD_REQ_QALL)) \
- & s->imask)
-
-#define SOC_SETIMASK(s, i) \
-do { (s)->imask = (i); \
- sbus_writel((i), (s)->regs + IMASK); \
-} while(0)
-
-/* XRAM
- *
- * This is a 64KB register area. It accepts only halfword access.
- * That's why here are the following inline functions...
- */
-
-typedef void __iomem *xram_p;
-
-/* Get 32bit number from XRAM */
-static inline u32 xram_get_32(xram_p x)
-{
- return ((sbus_readw(x + 0x00UL) << 16) |
- (sbus_readw(x + 0x02UL)));
-}
-
-/* Like the above, but when we don't care about the high 16 bits */
-static inline u32 xram_get_32low(xram_p x)
-{
- return (u32) sbus_readw(x + 0x02UL);
-}
-
-static inline u16 xram_get_16(xram_p x)
-{
- return sbus_readw(x);
-}
-
-static inline u8 xram_get_8(xram_p x)
-{
- if ((unsigned long)x & 0x1UL) {
- x = x - 1;
- return (u8) sbus_readw(x);
- } else {
- return (u8) (sbus_readw(x) >> 8);
- }
-}
-
-static inline void xram_copy_from(void *p, xram_p x, int len)
-{
- for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
- u32 val, *p32 = p;
-
- val = ((sbus_readw(x + 0x00UL) << 16) |
- (sbus_readw(x + 0x02UL)));
- *p32++ = val;
- p = p32;
- }
-}
-
-static inline void xram_copy_to(xram_p x, void *p, int len)
-{
- for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
- u32 tmp, *p32 = p;
-
- tmp = *p32++;
- p = p32;
- sbus_writew(tmp >> 16, x + 0x00UL);
- sbus_writew(tmp, x + 0x02UL);
- }
-}
-
-static inline void xram_bzero(xram_p x, int len)
-{
- for (len >>= 1; len > 0; len--, x += sizeof(u16))
- sbus_writew(0, x);
-}
-
-/* Circular Queue */
-
-#define SOC_CQ_REQ_OFFSET (0x100 * sizeof(u16))
-#define SOC_CQ_RSP_OFFSET (0x110 * sizeof(u16))
-
-typedef struct {
- u32 address;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} soc_hw_cq;
-
-#define SOC_PORT_A 0x0000 /* From/To Port A */
-#define SOC_PORT_B 0x0001 /* From/To Port A */
-#define SOC_FC_HDR 0x0002 /* Contains FC Header */
-#define SOC_NORSP 0x0004 /* Don't generate response nor interrupt */
-#define SOC_NOINT 0x0008 /* Generate response but not interrupt */
-#define SOC_XFERRDY 0x0010 /* Generate XFERRDY */
-#define SOC_IGNOREPARAM 0x0020 /* Ignore PARAM field in the FC header */
-#define SOC_COMPLETE 0x0040 /* Command completed */
-#define SOC_UNSOLICITED 0x0080 /* For request this is the packet to establish unsolicited pools, */
- /* for rsp this is unsolicited packet */
-#define SOC_STATUS 0x0100 /* State change (on/off line) */
-
-typedef struct {
- u32 token;
- u16 flags;
- u8 class;
- u8 segcnt;
- u32 bytecnt;
-} soc_hdr;
-
-typedef struct {
- u32 base;
- u32 count;
-} soc_data;
-
-#define SOC_CQTYPE_OUTBOUND 0x01
-#define SOC_CQTYPE_INBOUND 0x02
-#define SOC_CQTYPE_SIMPLE 0x03
-#define SOC_CQTYPE_IO_WRITE 0x04
-#define SOC_CQTYPE_IO_READ 0x05
-#define SOC_CQTYPE_UNSOLICITED 0x06
-#define SOC_CQTYPE_DIAG 0x07
-#define SOC_CQTYPE_OFFLINE 0x08
-#define SOC_CQTYPE_RESPONSE 0x10
-#define SOC_CQTYPE_INLINE 0x20
-
-#define SOC_CQFLAGS_CONT 0x01
-#define SOC_CQFLAGS_FULL 0x02
-#define SOC_CQFLAGS_BADHDR 0x04
-#define SOC_CQFLAGS_BADPKT 0x08
-
-typedef struct {
- soc_hdr shdr;
- soc_data data[3];
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} soc_req;
-
-#define SOC_OK 0
-#define SOC_P_RJT 2
-#define SOC_F_RJT 3
-#define SOC_P_BSY 4
-#define SOC_F_BSY 5
-#define SOC_ONLINE 0x10
-#define SOC_OFFLINE 0x11
-#define SOC_TIMEOUT 0x12
-#define SOC_OVERRUN 0x13
-#define SOC_UNKOWN_CQ_TYPE 0x20
-#define SOC_BAD_SEG_CNT 0x21
-#define SOC_MAX_XCHG_EXCEEDED 0x22
-#define SOC_BAD_XID 0x23
-#define SOC_XCHG_BUSY 0x24
-#define SOC_BAD_POOL_ID 0x25
-#define SOC_INSUFFICIENT_CQES 0x26
-#define SOC_ALLOC_FAIL 0x27
-#define SOC_BAD_SID 0x28
-#define SOC_NO_SEG_INIT 0x29
-
-typedef struct {
- soc_hdr shdr;
- u32 status;
- soc_data data;
- u8 xxx1[12];
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} soc_rsp;
-
-/* }}} */
-
-/* Now our software structures and constants we use to drive the beast {{{ */
-
-#define SOC_CQ_REQ0_SIZE 4
-#define SOC_CQ_REQ1_SIZE 64
-#define SOC_CQ_RSP0_SIZE 8
-#define SOC_CQ_RSP1_SIZE 4
-
-#define SOC_SOLICITED_RSP_Q 0
-#define SOC_UNSOLICITED_RSP_Q 1
-
-struct soc;
-
-typedef struct {
- /* This must come first */
- fc_channel fc;
- struct soc *s;
- u16 flags;
- u16 mask;
-} soc_port;
-
-typedef struct {
- soc_hw_cq __iomem *hw_cq; /* Related XRAM cq */
- soc_req __iomem *pool;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} soc_cq_rsp;
-
-typedef struct {
- soc_hw_cq __iomem *hw_cq; /* Related XRAM cq */
- soc_req *pool;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} soc_cq_req;
-
-struct soc {
- spinlock_t lock;
- soc_port port[2]; /* Every SOC has one or two FC ports */
- soc_cq_req req[2]; /* Request CQs */
- soc_cq_rsp rsp[2]; /* Response CQs */
- int soc_no;
- void __iomem *regs;
- xram_p xram;
- fc_wwn wwn;
- u32 imask; /* Our copy of regs->imask */
- u32 cfg; /* Our copy of regs->cfg */
- char serv_params[80];
- struct soc *next;
- int curr_port; /* Which port will have priority to fcp_queue_empty */
-
- soc_req *req_cpu;
- u32 req_dvma;
-};
-
-/* }}} */
-
-#endif /* !(__SOC_H) */
diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c
deleted file mode 100644
index c903ebfab52..00000000000
--- a/drivers/fc4/socal.c
+++ /dev/null
@@ -1,904 +0,0 @@
-/* socal.c: Sparc SUNW,socal (SOC+) Fibre Channel Sbus adapter support.
- *
- * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- *
- * Sources:
- * Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
- * dpANS Fibre Channel Protocol for SCSI (X3.269-199X), Rev. 012, 1995
- * SOC+ Programming Guide 0.1
- * Fibre Channel Arbitrated Loop (FC-AL), dpANS rev. 4.5, 1995
- *
- * Supported hardware:
- * On-board SOC+ adapters of Ultra Enterprise servers and sun4d.
- */
-
-static char *version =
- "socal.c: SOC+ driver v1.1 9/Feb/99 Jakub Jelinek (jj@ultra.linux.cz)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/errno.h>
-#include <asm/byteorder.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-
-/* #define SOCALDEBUG */
-/* #define HAVE_SOCAL_UCODE */
-/* #define USE_64BIT_MODE */
-
-#include "fcp_impl.h"
-#include "socal.h"
-#ifdef HAVE_SOCAL_UCODE
-#include "socal_asm.h"
-#endif
-
-#define socal_printk printk ("socal%d: ", s->socal_no); printk
-
-#ifdef SOCALDEBUG
-#define SOD(x) socal_printk x;
-#else
-#define SOD(x)
-#endif
-
-#define for_each_socal(s) for (s = socals; s; s = s->next)
-struct socal *socals = NULL;
-
-static void socal_copy_from_xram(void *d, void __iomem *xram, long size)
-{
- u32 *dp = (u32 *) d;
- while (size) {
- *dp++ = sbus_readl(xram);
- xram += sizeof(u32);
- size -= sizeof(u32);
- }
-}
-
-static void socal_copy_to_xram(void __iomem *xram, void *s, long size)
-{
- u32 *sp = (u32 *) s;
- while (size) {
- u32 val = *sp++;
- sbus_writel(val, xram);
- xram += sizeof(u32);
- size -= sizeof(u32);
- }
-}
-
-#ifdef HAVE_SOCAL_UCODE
-static void socal_bzero(unsigned long xram, int size)
-{
- while (size) {
- sbus_writel(0, xram);
- xram += sizeof(u32);
- size -= sizeof(u32);
- }
-}
-#endif
-
-static inline void socal_disable(struct socal *s)
-{
- sbus_writel(0, s->regs + IMASK);
- sbus_writel(SOCAL_CMD_SOFT_RESET, s->regs + CMD);
-}
-
-static inline void socal_enable(struct socal *s)
-{
- SOD(("enable %08x\n", s->cfg))
- sbus_writel(0, s->regs + SAE);
- sbus_writel(s->cfg, s->regs + CFG);
- sbus_writel(SOCAL_CMD_RSP_QALL, s->regs + CMD);
- SOCAL_SETIMASK(s, SOCAL_IMASK_RSP_QALL | SOCAL_IMASK_SAE);
- SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
-}
-
-static void socal_reset(fc_channel *fc)
-{
- socal_port *port = (socal_port *)fc;
- struct socal *s = port->s;
-
- /* FIXME */
- socal_disable(s);
- s->req[0].seqno = 1;
- s->req[1].seqno = 1;
- s->rsp[0].seqno = 1;
- s->rsp[1].seqno = 1;
- s->req[0].in = 0;
- s->req[1].in = 0;
- s->rsp[0].in = 0;
- s->rsp[1].in = 0;
- s->req[0].out = 0;
- s->req[1].out = 0;
- s->rsp[0].out = 0;
- s->rsp[1].out = 0;
-
- /* FIXME */
- socal_enable(s);
-}
-
-static inline void socal_solicited(struct socal *s, unsigned long qno)
-{
- socal_rsp *hwrsp;
- socal_cq *sw_cq;
- int token;
- int status;
- fc_channel *fc;
-
- sw_cq = &s->rsp[qno];
-
- /* Finally an improvement against old SOC :) */
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- SOD (("socal_solicited, %d packets arrived\n",
- (sw_cq->in - sw_cq->out) & sw_cq->last))
- for (;;) {
- hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
- SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out))
-
-#if defined(SOCALDEBUG) && 0
- {
- u32 *u = (u32 *)hwrsp;
- SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- u += 8;
- SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- u = (u32 *)s->xram;
- while (u < ((u32 *)s->regs)) {
- if (sbus_readl(&u[0]) == 0x00003000 ||
- sbus_readl(&u[0]) == 0x00003801) {
- SOD(("Found at %04lx\n",
- (unsigned long)u - (unsigned long)s->xram))
- SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- sbus_readl(&u[0]), sbus_readl(&u[1]),
- sbus_readl(&u[2]), sbus_readl(&u[3]),
- sbus_readl(&u[4]), sbus_readl(&u[5]),
- sbus_readl(&u[6]), sbus_readl(&u[7])))
- u += 8;
- SOD((" %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- sbus_readl(&u[0]), sbus_readl(&u[1]),
- sbus_readl(&u[2]), sbus_readl(&u[3]),
- sbus_readl(&u[4]), sbus_readl(&u[5]),
- sbus_readl(&u[6]), sbus_readl(&u[7])))
- u -= 8;
- }
- u++;
- }
- }
-#endif
-
- token = hwrsp->shdr.token;
- status = hwrsp->status;
- fc = (fc_channel *)(&s->port[(token >> 11) & 1]);
-
- SOD(("Solicited token %08x status %08x\n", token, status))
- if (status == SOCAL_OK) {
- fcp_receive_solicited(fc, token >> 12,
- token & ((1 << 11) - 1),
- FC_STATUS_OK, NULL);
- } else {
- /* We have intentionally defined FC_STATUS_* constants
- * to match SOCAL_* constants, otherwise we'd have to
- * translate status.
- */
- fcp_receive_solicited(fc, token >> 12,
- token & ((1 << 11) - 1), status, &hwrsp->fchdr);
- }
-
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
-
- if (sw_cq->out == sw_cq->in) {
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- if (sw_cq->out == sw_cq->in) {
- /* Tell the hardware about it */
- sbus_writel((sw_cq->out << 24) |
- (SOCAL_CMD_RSP_QALL &
- ~(SOCAL_CMD_RSP_Q0 << qno)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- if (sw_cq->out == sw_cq->in)
- break;
- }
- }
- }
-}
-
-static inline void socal_request (struct socal *s, u32 cmd)
-{
- SOCAL_SETIMASK(s, s->imask & ~(cmd & SOCAL_CMD_REQ_QALL));
- SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
-
- SOD(("Queues available %08x OUT %X\n", cmd, s->regs->reqpr[0]))
- if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) {
- fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port]));
- if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out))
- fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
- } else {
- fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
- }
- if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE)
- s->curr_port ^= 1;
-}
-
-static inline void socal_unsolicited (struct socal *s, unsigned long qno)
-{
- socal_rsp *hwrsp, *hwrspc;
- socal_cq *sw_cq;
- int count;
- int status;
- int flags;
- fc_channel *fc;
-
- sw_cq = &s->rsp[qno];
-
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- SOD (("socal_unsolicited, %d packets arrived, in %d\n",
- (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in))
- while (sw_cq->in != sw_cq->out) {
- /* ...real work per entry here... */
- hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
- SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out))
-
-#if defined(SOCALDEBUG) && 0
- {
- u32 *u = (u32 *)hwrsp;
- SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- u += 8;
- SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
- u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
- }
-#endif
-
- hwrspc = NULL;
- flags = hwrsp->shdr.flags;
- count = hwrsp->count;
- fc = (fc_channel *)&s->port[flags & SOCAL_PORT_B];
- SOD(("FC %08lx\n", (long)fc))
-
- if (count != 1) {
- /* Ugh, continuation entries */
- u8 in;
-
- if (count != 2) {
- printk("%s: Too many continuations entries %d\n",
- fc->name, count);
- goto update_out;
- }
-
- in = sw_cq->in;
- if (in < sw_cq->out)
- in += sw_cq->last + 1;
- if (in < sw_cq->out + 2) {
- /* Ask the hardware if they haven't arrived yet. */
- sbus_writel((sw_cq->out << 24) |
- (SOCAL_CMD_RSP_QALL &
- ~(SOCAL_CMD_RSP_Q0 << qno)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- in = sw_cq->in;
- if (in < sw_cq->out)
- in += sw_cq->last + 1;
- if (in < sw_cq->out + 2) /* Nothing came, let us wait */
- return;
- }
- if (sw_cq->out == sw_cq->last)
- hwrspc = (socal_rsp *)sw_cq->pool;
- else
- hwrspc = hwrsp + 1;
- }
-
- switch (flags & ~SOCAL_PORT_B) {
- case SOCAL_STATUS:
- status = hwrsp->status;
- switch (status) {
- case SOCAL_ONLINE:
- SOD(("State change to ONLINE\n"));
- fcp_state_change(fc, FC_STATE_ONLINE);
- break;
- case SOCAL_ONLINE_LOOP:
- SOD(("State change to ONLINE_LOOP\n"));
- fcp_state_change(fc, FC_STATE_ONLINE);
- break;
- case SOCAL_OFFLINE:
- SOD(("State change to OFFLINE\n"));
- fcp_state_change(fc, FC_STATE_OFFLINE);
- break;
- default:
- printk ("%s: Unknown STATUS no %d\n",
- fc->name, status);
- break;
- };
-
- break;
- case (SOCAL_UNSOLICITED|SOCAL_FC_HDR):
- {
- int r_ctl = *((u8 *)&hwrsp->fchdr);
- unsigned len;
-
- if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) {
- len = hwrsp->shdr.bytecnt;
- if (len < 4 || !hwrspc) {
- printk ("%s: Invalid R_CTL %02x "
- "continuation entries\n",
- fc->name, r_ctl);
- } else {
- if (len > 60)
- len = 60;
- if (*(u32 *)hwrspc == LS_DISPLAY) {
- int i;
-
- for (i = 4; i < len; i++)
- if (((u8 *)hwrspc)[i] == '\n')
- ((u8 *)hwrspc)[i] = ' ';
- ((u8 *)hwrspc)[len] = 0;
- printk ("%s message: %s\n",
- fc->name, ((u8 *)hwrspc) + 4);
- } else {
- printk ("%s: Unknown LS_CMD "
- "%08x\n", fc->name,
- *(u32 *)hwrspc);
- }
- }
- } else {
- printk ("%s: Unsolicited R_CTL %02x "
- "not handled\n", fc->name, r_ctl);
- }
- }
- break;
- default:
- printk ("%s: Unexpected flags %08x\n", fc->name, flags);
- break;
- };
-update_out:
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
-
- if (hwrspc) {
- if (++sw_cq->out > sw_cq->last) {
- sw_cq->seqno++;
- sw_cq->out = 0;
- }
- }
-
- if (sw_cq->out == sw_cq->in) {
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- if (sw_cq->out == sw_cq->in) {
- /* Tell the hardware about it */
- sbus_writel((sw_cq->out << 24) |
- (SOCAL_CMD_RSP_QALL &
- ~(SOCAL_CMD_RSP_Q0 << qno)),
- s->regs + CMD);
-
- /* Read it, so that we're sure it has been updated */
- sbus_readl(s->regs + CMD);
- sw_cq->in = sbus_readb(s->regs + RESP + qno);
- }
- }
- }
-}
-
-static irqreturn_t socal_intr(int irq, void *dev_id)
-{
- u32 cmd;
- unsigned long flags;
- register struct socal *s = (struct socal *)dev_id;
-
- spin_lock_irqsave(&s->lock, flags);
- cmd = sbus_readl(s->regs + CMD);
- for (; (cmd = SOCAL_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) {
-#ifdef SOCALDEBUG
- static int cnt = 0;
- if (cnt++ < 50)
- printk("soc_intr %08x\n", cmd);
-#endif
- if (cmd & SOCAL_CMD_RSP_Q2)
- socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q);
- if (cmd & SOCAL_CMD_RSP_Q1)
- socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q);
- if (cmd & SOCAL_CMD_RSP_Q0)
- socal_solicited (s, SOCAL_SOLICITED_RSP_Q);
- if (cmd & SOCAL_CMD_REQ_QALL)
- socal_request (s, cmd);
- }
- spin_unlock_irqrestore(&s->lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#define TOKEN(proto, port, token) (((proto)<<12)|(token)|(port))
-
-static int socal_hw_enque (fc_channel *fc, fcp_cmnd *fcmd)
-{
- socal_port *port = (socal_port *)fc;
- struct socal *s = port->s;
- unsigned long qno;
- socal_cq *sw_cq;
- int cq_next_in;
- socal_req *request;
- fc_hdr *fch;
- int i;
-
- if (fcmd->proto == TYPE_SCSI_FCP)
- qno = 1;
- else
- qno = 0;
- SOD(("Putting a FCP packet type %d into hw queue %d\n", fcmd->proto, qno))
- if (s->imask & (SOCAL_IMASK_REQ_Q0 << qno)) {
- SOD(("EIO %08x\n", s->imask))
- return -EIO;
- }
- sw_cq = s->req + qno;
- cq_next_in = (sw_cq->in + 1) & sw_cq->last;
-
- if (cq_next_in == sw_cq->out &&
- cq_next_in == (sw_cq->out = sbus_readb(s->regs + REQP + qno))) {
- SOD(("%d IN %d OUT %d LAST %d\n",
- qno, sw_cq->in,
- sw_cq->out, sw_cq->last))
- SOCAL_SETIMASK(s, s->imask | (SOCAL_IMASK_REQ_Q0 << qno));
- SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
-
- /* If queue is full, just say NO. */
- return -EBUSY;
- }
-
- request = sw_cq->pool + sw_cq->in;
- fch = &request->fchdr;
-
- switch (fcmd->proto) {
- case TYPE_SCSI_FCP:
- request->shdr.token = TOKEN(TYPE_SCSI_FCP, port->mask, fcmd->token);
- request->data[0].base = fc->dma_scsi_cmd + fcmd->token * sizeof(fcp_cmd);
- request->data[0].count = sizeof(fcp_cmd);
- request->data[1].base = fc->dma_scsi_rsp + fcmd->token * fc->rsp_size;
- request->data[1].count = fc->rsp_size;
- if (fcmd->data) {
- request->shdr.segcnt = 3;
- i = fc->scsi_cmd_pool[fcmd->token].fcp_data_len;
- request->shdr.bytecnt = i;
- request->data[2].base = fcmd->data;
- request->data[2].count = i;
- request->type = (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ?
- SOCAL_CQTYPE_IO_WRITE : SOCAL_CQTYPE_IO_READ;
- } else {
- request->shdr.segcnt = 2;
- request->shdr.bytecnt = 0;
- request->data[2].base = 0;
- request->data[2].count = 0;
- request->type = SOCAL_CQTYPE_SIMPLE;
- }
- FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fcmd->did);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- fch->param = 0;
- request->shdr.flags = port->flags;
- request->shdr.class = fc->posmap ? 3 : 2;
- break;
-
- case PROTO_OFFLINE:
- memset (request, 0, sizeof(*request));
- request->shdr.token = TOKEN(PROTO_OFFLINE, port->mask, fcmd->token);
- request->type = SOCAL_CQTYPE_OFFLINE;
- FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fcmd->did);
- FILL_FCHDR_SID(fch, fc->sid);
- FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
- FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
- FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
- request->shdr.flags = port->flags;
- break;
-
- case PROTO_REPORT_AL_MAP:
- memset (request, 0, sizeof(*request));
- request->shdr.token = TOKEN(PROTO_REPORT_AL_MAP, port->mask, fcmd->token);
- request->type = SOCAL_CQTYPE_REPORT_MAP;
- request->shdr.flags = port->flags;
- request->shdr.segcnt = 1;
- request->shdr.bytecnt = sizeof(fc_al_posmap);
- request->data[0].base = fcmd->cmd;
- request->data[0].count = sizeof(fc_al_posmap);
- break;
-
- default:
- request->shdr.token = TOKEN(fcmd->proto, port->mask, fcmd->token);
- request->shdr.class = fc->posmap ? 3 : 2;
- request->shdr.flags = port->flags;
- memcpy (fch, &fcmd->fch, sizeof(fc_hdr));
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = fcmd->class;
- switch (fcmd->class) {
- case FC_CLASS_OUTBOUND:
- request->data[0].base = fcmd->cmd;
- request->data[0].count = fcmd->cmdlen;
- request->type = SOCAL_CQTYPE_OUTBOUND;
- request->shdr.bytecnt = fcmd->cmdlen;
- request->shdr.segcnt = 1;
- break;
- case FC_CLASS_INBOUND:
- request->data[0].base = fcmd->rsp;
- request->data[0].count = fcmd->rsplen;
- request->type = SOCAL_CQTYPE_INBOUND;
- request->shdr.bytecnt = 0;
- request->shdr.segcnt = 1;
- break;
- case FC_CLASS_SIMPLE:
- request->data[0].base = fcmd->cmd;
- request->data[1].base = fcmd->rsp;
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = SOCAL_CQTYPE_SIMPLE;
- request->shdr.bytecnt = fcmd->cmdlen;
- request->shdr.segcnt = 2;
- break;
- case FC_CLASS_IO_READ:
- case FC_CLASS_IO_WRITE:
- request->data[0].base = fcmd->cmd;
- request->data[1].base = fcmd->rsp;
- request->data[0].count = fcmd->cmdlen;
- request->data[1].count = fcmd->rsplen;
- request->type = (fcmd->class == FC_CLASS_IO_READ) ? SOCAL_CQTYPE_IO_READ : SOCAL_CQTYPE_IO_WRITE;
- if (fcmd->data) {
- request->data[2].base = fcmd->data;
- request->data[2].count = fcmd->datalen;
- request->shdr.bytecnt = fcmd->datalen;
- request->shdr.segcnt = 3;
- } else {
- request->shdr.bytecnt = 0;
- request->shdr.segcnt = 2;
- }
- break;
- }
- break;
- }
-
- request->count = 1;
- request->flags = 0;
- request->seqno = sw_cq->seqno;
-
- SOD(("queueing token %08x\n", request->shdr.token))
-
- /* And now tell the SOCAL about it */
-
- if (++sw_cq->in > sw_cq->last) {
- sw_cq->in = 0;
- sw_cq->seqno++;
- }
-
- SOD(("Putting %08x into cmd\n", SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno)))
-
- sbus_writel(SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno),
- s->regs + CMD);
-
- /* Read so that command is completed */
- sbus_readl(s->regs + CMD);
-
- return 0;
-}
-
-static inline void socal_download_fw(struct socal *s)
-{
-#ifdef HAVE_SOCAL_UCODE
- SOD(("Loading %ld bytes from %p to %p\n", sizeof(socal_ucode), socal_ucode, s->xram))
- socal_copy_to_xram(s->xram, socal_ucode, sizeof(socal_ucode));
- SOD(("Clearing the rest of memory\n"))
- socal_bzero (s->xram + sizeof(socal_ucode), 65536 - sizeof(socal_ucode));
- SOD(("Done\n"))
-#endif
-}
-
-/* Check for what the best SBUS burst we can use happens
- * to be on this machine.
- */
-static inline void socal_init_bursts(struct socal *s, struct sbus_dev *sdev)
-{
- int bsizes, bsizes_more;
- u32 cfg;
-
- bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff);
- bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff);
- bsizes &= bsizes_more;
-#ifdef USE_64BIT_MODE
-#ifdef __sparc_v9__
- mmu_set_sbus64(sdev, bsizes >> 16);
-#endif
-#endif
- if ((bsizes & 0x7f) == 0x7f)
- cfg = SOCAL_CFG_BURST_64;
- else if ((bsizes & 0x3f) == 0x3f)
- cfg = SOCAL_CFG_BURST_32;
- else if ((bsizes & 0x1f) == 0x1f)
- cfg = SOCAL_CFG_BURST_16;
- else
- cfg = SOCAL_CFG_BURST_4;
-#ifdef USE_64BIT_MODE
-#ifdef __sparc_v9__
- /* What is BURST_128? -jj */
- if ((bsizes & 0x780000) == 0x780000)
- cfg |= (SOCAL_CFG_BURST_64 << 8) | SOCAL_CFG_SBUS_ENHANCED;
- else if ((bsizes & 0x380000) == 0x380000)
- cfg |= (SOCAL_CFG_BURST_32 << 8) | SOCAL_CFG_SBUS_ENHANCED;
- else if ((bsizes & 0x180000) == 0x180000)
- cfg |= (SOCAL_CFG_BURST_16 << 8) | SOCAL_CFG_SBUS_ENHANCED;
- else
- cfg |= (SOCAL_CFG_BURST_8 << 8) | SOCAL_CFG_SBUS_ENHANCED;
-#endif
-#endif
- s->cfg = cfg;
-}
-
-static inline void socal_init(struct sbus_dev *sdev, int no)
-{
- unsigned char tmp[60];
- int propl;
- struct socal *s;
- static unsigned version_printed = 0;
- socal_hw_cq cq[8];
- int size, i;
- int irq, node;
-
- s = kzalloc (sizeof (struct socal), GFP_KERNEL);
- if (!s) return;
- spin_lock_init(&s->lock);
- s->socal_no = no;
-
- SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n",
- (long)socals, (long)socal_intr, (long)socal_hw_enque))
- if (version_printed++ == 0)
- printk (version);
-
- s->port[0].fc.module = THIS_MODULE;
- s->port[1].fc.module = THIS_MODULE;
-
- s->next = socals;
- socals = s;
- s->port[0].fc.dev = sdev;
- s->port[1].fc.dev = sdev;
- s->port[0].s = s;
- s->port[1].s = s;
-
- s->port[0].fc.next = &s->port[1].fc;
-
- /* World Wide Name of SOCAL */
- propl = prom_getproperty (sdev->prom_node, "wwn", tmp, sizeof(tmp));
- if (propl != sizeof (fc_wwn)) {
- s->wwn.naaid = NAAID_IEEE_REG;
- s->wwn.nportid = 0x123;
- s->wwn.hi = 0x1234;
- s->wwn.lo = 0x12345678;
- } else
- memcpy (&s->wwn, tmp, sizeof (fc_wwn));
-
- memcpy (&s->port[0].fc.wwn_nport, &s->wwn, sizeof (fc_wwn));
- s->port[0].fc.wwn_nport.lo++;
- memcpy (&s->port[1].fc.wwn_nport, &s->wwn, sizeof (fc_wwn));
- s->port[1].fc.wwn_nport.lo+=2;
-
- node = prom_getchild (sdev->prom_node);
- while (node && (node = prom_searchsiblings (node, "sf"))) {
- int port;
-
- port = prom_getintdefault(node, "port#", -1);
- switch (port) {
- case 0:
- case 1:
- if (prom_getproplen(node, "port-wwn") == sizeof (fc_wwn))
- prom_getproperty (node, "port-wwn",
- (char *)&s->port[port].fc.wwn_nport,
- sizeof (fc_wwn));
- break;
- default:
- break;
- };
-
- node = prom_getsibling(node);
- }
-
- memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
- memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
- SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n",
- *(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo,
- *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
- *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
-
- s->port[0].fc.sid = 1;
- s->port[1].fc.sid = 17;
- s->port[0].fc.did = 2;
- s->port[1].fc.did = 18;
-
- s->port[0].fc.reset = socal_reset;
- s->port[1].fc.reset = socal_reset;
-
- if (sdev->num_registers == 1) {
- s->eeprom = sbus_ioremap(&sdev->resource[0], 0,
- sdev->reg_addrs[0].reg_size, "socal xram");
- if (sdev->reg_addrs[0].reg_size > 0x20000)
- s->xram = s->eeprom + 0x10000UL;
- else
- s->xram = s->eeprom;
- s->regs = (s->xram + 0x10000UL);
- } else {
- /* E.g. starfire presents 3 registers for SOCAL */
- s->xram = sbus_ioremap(&sdev->resource[1], 0,
- sdev->reg_addrs[1].reg_size, "socal xram");
- s->regs = sbus_ioremap(&sdev->resource[2], 0,
- sdev->reg_addrs[2].reg_size, "socal regs");
- }
-
- socal_init_bursts(s, sdev);
-
- SOD(("Disabling SOCAL\n"))
-
- socal_disable (s);
-
- irq = sdev->irqs[0];
-
- if (request_irq (irq, socal_intr, IRQF_SHARED, "SOCAL", (void *)s)) {
- socal_printk ("Cannot order irq %d to go\n", irq);
- socals = s->next;
- return;
- }
-
- SOD(("SOCAL uses IRQ %d\n", irq))
-
- s->port[0].fc.irq = irq;
- s->port[1].fc.irq = irq;
-
- sprintf (s->port[0].fc.name, "socal%d port A", no);
- sprintf (s->port[1].fc.name, "socal%d port B", no);
- s->port[0].flags = SOCAL_FC_HDR | SOCAL_PORT_A;
- s->port[1].flags = SOCAL_FC_HDR | SOCAL_PORT_B;
- s->port[1].mask = (1 << 11);
-
- s->port[0].fc.hw_enque = socal_hw_enque;
- s->port[1].fc.hw_enque = socal_hw_enque;
-
- socal_download_fw (s);
-
- SOD(("Downloaded firmware\n"))
-
- /* Now setup xram circular queues */
- memset (cq, 0, sizeof(cq));
-
- size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE +
- SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE +
- SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req);
- s->req_cpu = sbus_alloc_consistent(sdev, size, &s->req_dvma);
- s->req[0].pool = s->req_cpu;
- cq[0].address = s->req_dvma;
- s->req[1].pool = s->req[0].pool + SOCAL_CQ_REQ0_SIZE;
- s->rsp[0].pool = s->req[1].pool + SOCAL_CQ_REQ1_SIZE;
- s->rsp[1].pool = s->rsp[0].pool + SOCAL_CQ_RSP0_SIZE;
- s->rsp[2].pool = s->rsp[1].pool + SOCAL_CQ_RSP1_SIZE;
-
- s->req[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET);
- s->req[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_REQ_OFFSET + sizeof(socal_hw_cq));
- s->rsp[0].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET);
- s->rsp[1].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + sizeof(socal_hw_cq));
- s->rsp[2].hw_cq = (socal_hw_cq __iomem *)(s->xram + SOCAL_CQ_RSP_OFFSET + 2 * sizeof(socal_hw_cq));
-
- cq[1].address = cq[0].address + (SOCAL_CQ_REQ0_SIZE * sizeof(socal_req));
- cq[4].address = cq[1].address + (SOCAL_CQ_REQ1_SIZE * sizeof(socal_req));
- cq[5].address = cq[4].address + (SOCAL_CQ_RSP0_SIZE * sizeof(socal_req));
- cq[6].address = cq[5].address + (SOCAL_CQ_RSP1_SIZE * sizeof(socal_req));
-
- cq[0].last = SOCAL_CQ_REQ0_SIZE - 1;
- cq[1].last = SOCAL_CQ_REQ1_SIZE - 1;
- cq[4].last = SOCAL_CQ_RSP0_SIZE - 1;
- cq[5].last = SOCAL_CQ_RSP1_SIZE - 1;
- cq[6].last = SOCAL_CQ_RSP2_SIZE - 1;
- for (i = 0; i < 8; i++)
- cq[i].seqno = 1;
-
- s->req[0].last = SOCAL_CQ_REQ0_SIZE - 1;
- s->req[1].last = SOCAL_CQ_REQ1_SIZE - 1;
- s->rsp[0].last = SOCAL_CQ_RSP0_SIZE - 1;
- s->rsp[1].last = SOCAL_CQ_RSP1_SIZE - 1;
- s->rsp[2].last = SOCAL_CQ_RSP2_SIZE - 1;
-
- s->req[0].seqno = 1;
- s->req[1].seqno = 1;
- s->rsp[0].seqno = 1;
- s->rsp[1].seqno = 1;
- s->rsp[2].seqno = 1;
-
- socal_copy_to_xram(s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq));
-
- SOD(("Setting up params\n"))
-
- /* Make our sw copy of SOCAL service parameters */
- socal_copy_from_xram(s->serv_params, s->xram + 0x280, sizeof (s->serv_params));
-
- s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params;
- s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
- s->port[1].fc.common_svc = (common_svc_parm *)&s->serv_params;
- s->port[1].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
-
- socal_enable (s);
-
- SOD(("Enabled SOCAL\n"))
-}
-
-static int __init socal_probe(void)
-{
- struct sbus_bus *sbus;
- struct sbus_dev *sdev = NULL;
- struct socal *s;
- int cards = 0;
-
- for_each_sbus(sbus) {
- for_each_sbusdev(sdev, sbus) {
- if(!strcmp(sdev->prom_name, "SUNW,socal")) {
- socal_init(sdev, cards);
- cards++;
- }
- }
- }
- if (!cards)
- return -EIO;
-
- for_each_socal(s)
- if (s->next)
- s->port[1].fc.next = &s->next->port[0].fc;
-
- fcp_init (&socals->port[0].fc);
- return 0;
-}
-
-static void __exit socal_cleanup(void)
-{
- struct socal *s;
- int irq;
- struct sbus_dev *sdev;
-
- for_each_socal(s) {
- irq = s->port[0].fc.irq;
- free_irq (irq, s);
-
- fcp_release(&(s->port[0].fc), 2);
-
- sdev = s->port[0].fc.dev;
- if (sdev->num_registers == 1) {
- sbus_iounmap(s->eeprom, sdev->reg_addrs[0].reg_size);
- } else {
- sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size);
- sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size);
- }
- sbus_free_consistent(sdev,
- (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE +
- SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE +
- SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req),
- s->req_cpu, s->req_dvma);
- }
-}
-
-module_init(socal_probe);
-module_exit(socal_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/fc4/socal.h b/drivers/fc4/socal.h
deleted file mode 100644
index 774edf68e4d..00000000000
--- a/drivers/fc4/socal.h
+++ /dev/null
@@ -1,314 +0,0 @@
-/* socal.h: Definitions for Sparc SUNW,socal (SOC+) Fibre Channel Sbus driver.
- *
- * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#ifndef __SOCAL_H
-#define __SOCAL_H
-
-#include "fc.h"
-#include "fcp.h"
-#include "fcp_impl.h"
-
-/* Hardware register offsets and constants first {{{ */
-#define CFG 0x00UL
-#define SAE 0x04UL
-#define CMD 0x08UL
-#define IMASK 0x0cUL
-#define REQP 0x10UL
-#define RESP 0x14UL
-
-/* Config Register */
-#define SOCAL_CFG_EXT_RAM_BANK_MASK 0x07000000
-#define SOCAL_CFG_EEPROM_BANK_MASK 0x00030000
-#define SOCAL_CFG_BURST64_MASK 0x00000700
-#define SOCAL_CFG_SBUS_PARITY_TEST 0x00000020
-#define SOCAL_CFG_SBUS_PARITY_CHECK 0x00000010
-#define SOCAL_CFG_SBUS_ENHANCED 0x00000008
-#define SOCAL_CFG_BURST_MASK 0x00000007
-/* Bursts */
-#define SOCAL_CFG_BURST_4 0x00000000
-#define SOCAL_CFG_BURST_8 0x00000003
-#define SOCAL_CFG_BURST_16 0x00000004
-#define SOCAL_CFG_BURST_32 0x00000005
-#define SOCAL_CFG_BURST_64 0x00000006
-#define SOCAL_CFG_BURST_128 0x00000007
-
-/* Slave Access Error Register */
-#define SOCAL_SAE_ALIGNMENT 0x00000004
-#define SOCAL_SAE_UNSUPPORTED 0x00000002
-#define SOCAL_SAE_PARITY 0x00000001
-
-/* Command & Status Register */
-#define SOCAL_CMD_RSP_QALL 0x000f0000
-#define SOCAL_CMD_RSP_Q0 0x00010000
-#define SOCAL_CMD_RSP_Q1 0x00020000
-#define SOCAL_CMD_RSP_Q2 0x00040000
-#define SOCAL_CMD_RSP_Q3 0x00080000
-#define SOCAL_CMD_REQ_QALL 0x00000f00
-#define SOCAL_CMD_REQ_Q0 0x00000100
-#define SOCAL_CMD_REQ_Q1 0x00000200
-#define SOCAL_CMD_REQ_Q2 0x00000400
-#define SOCAL_CMD_REQ_Q3 0x00000800
-#define SOCAL_CMD_SAE 0x00000080
-#define SOCAL_CMD_INTR_PENDING 0x00000008
-#define SOCAL_CMD_NON_QUEUED 0x00000004
-#define SOCAL_CMD_IDLE 0x00000002
-#define SOCAL_CMD_SOFT_RESET 0x00000001
-
-/* Interrupt Mask Register */
-#define SOCAL_IMASK_RSP_QALL 0x000f0000
-#define SOCAL_IMASK_RSP_Q0 0x00010000
-#define SOCAL_IMASK_RSP_Q1 0x00020000
-#define SOCAL_IMASK_RSP_Q2 0x00040000
-#define SOCAL_IMASK_RSP_Q3 0x00080000
-#define SOCAL_IMASK_REQ_QALL 0x00000f00
-#define SOCAL_IMASK_REQ_Q0 0x00000100
-#define SOCAL_IMASK_REQ_Q1 0x00000200
-#define SOCAL_IMASK_REQ_Q2 0x00000400
-#define SOCAL_IMASK_REQ_Q3 0x00000800
-#define SOCAL_IMASK_SAE 0x00000080
-#define SOCAL_IMASK_NON_QUEUED 0x00000004
-
-#define SOCAL_INTR(s, cmd) \
- (((cmd & SOCAL_CMD_RSP_QALL) | ((~cmd) & SOCAL_CMD_REQ_QALL)) \
- & s->imask)
-
-#define SOCAL_SETIMASK(s, i) \
-do { (s)->imask = (i); \
- sbus_writel((i), (s)->regs + IMASK); \
-} while (0)
-
-#define SOCAL_MAX_EXCHANGES 1024
-
-/* XRAM
- *
- * This is a 64KB register area.
- * From the documentation, it seems like it is finally able to cope
- * at least with 1,2,4 byte accesses for read and 2,4 byte accesses for write.
- */
-
-/* Circular Queue */
-
-#define SOCAL_CQ_REQ_OFFSET 0x200
-#define SOCAL_CQ_RSP_OFFSET 0x220
-
-typedef struct {
- u32 address;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} socal_hw_cq;
-
-#define SOCAL_PORT_A 0x0000 /* From/To Port A */
-#define SOCAL_PORT_B 0x0001 /* From/To Port A */
-#define SOCAL_FC_HDR 0x0002 /* Contains FC Header */
-#define SOCAL_NORSP 0x0004 /* Don't generate response nor interrupt */
-#define SOCAL_NOINT 0x0008 /* Generate response but not interrupt */
-#define SOCAL_XFERRDY 0x0010 /* Generate XFERRDY */
-#define SOCAL_IGNOREPARAM 0x0020 /* Ignore PARAM field in the FC header */
-#define SOCAL_COMPLETE 0x0040 /* Command completed */
-#define SOCAL_UNSOLICITED 0x0080 /* For request this is the packet to establish unsolicited pools, */
- /* for rsp this is unsolicited packet */
-#define SOCAL_STATUS 0x0100 /* State change (on/off line) */
-#define SOCAL_RSP_HDR 0x0200 /* Return frame header in any case */
-
-typedef struct {
- u32 token;
- u16 flags;
- u8 class;
- u8 segcnt;
- u32 bytecnt;
-} socal_hdr;
-
-typedef struct {
- u32 base;
- u32 count;
-} socal_data;
-
-#define SOCAL_CQTYPE_NOP 0x00
-#define SOCAL_CQTYPE_OUTBOUND 0x01
-#define SOCAL_CQTYPE_INBOUND 0x02
-#define SOCAL_CQTYPE_SIMPLE 0x03
-#define SOCAL_CQTYPE_IO_WRITE 0x04
-#define SOCAL_CQTYPE_IO_READ 0x05
-#define SOCAL_CQTYPE_UNSOLICITED 0x06
-#define SOCAL_CQTYPE_BYPASS_DEV 0x06
-#define SOCAL_CQTYPE_DIAG 0x07
-#define SOCAL_CQTYPE_OFFLINE 0x08
-#define SOCAL_CQTYPE_ADD_POOL 0x09
-#define SOCAL_CQTYPE_DELETE_POOL 0x0a
-#define SOCAL_CQTYPE_ADD_BUFFER 0x0b
-#define SOCAL_CQTYPE_ADD_POOL_BUFFER 0x0c
-#define SOCAL_CQTYPE_REQUEST_ABORT 0x0d
-#define SOCAL_CQTYPE_REQUEST_LIP 0x0e
-#define SOCAL_CQTYPE_REPORT_MAP 0x0f
-#define SOCAL_CQTYPE_RESPONSE 0x10
-#define SOCAL_CQTYPE_INLINE 0x20
-
-#define SOCAL_CQFLAGS_CONT 0x01
-#define SOCAL_CQFLAGS_FULL 0x02
-#define SOCAL_CQFLAGS_BADHDR 0x04
-#define SOCAL_CQFLAGS_BADPKT 0x08
-
-typedef struct {
- socal_hdr shdr;
- socal_data data[3];
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_req;
-
-#define SOCAL_OK 0
-#define SOCAL_P_RJT 2
-#define SOCAL_F_RJT 3
-#define SOCAL_P_BSY 4
-#define SOCAL_F_BSY 5
-#define SOCAL_ONLINE 0x10
-#define SOCAL_OFFLINE 0x11
-#define SOCAL_TIMEOUT 0x12
-#define SOCAL_OVERRUN 0x13
-#define SOCAL_ONLINE_LOOP 0x14
-#define SOCAL_OLD_PORT 0x15
-#define SOCAL_AL_PORT 0x16
-#define SOCAL_UNKOWN_CQ_TYPE 0x20
-#define SOCAL_BAD_SEG_CNT 0x21
-#define SOCAL_MAX_XCHG_EXCEEDED 0x22
-#define SOCAL_BAD_XID 0x23
-#define SOCAL_XCHG_BUSY 0x24
-#define SOCAL_BAD_POOL_ID 0x25
-#define SOCAL_INSUFFICIENT_CQES 0x26
-#define SOCAL_ALLOC_FAIL 0x27
-#define SOCAL_BAD_SID 0x28
-#define SOCAL_NO_SEG_INIT 0x29
-#define SOCAL_BAD_DID 0x2a
-#define SOCAL_ABORTED 0x30
-#define SOCAL_ABORT_FAILED 0x31
-
-typedef struct {
- socal_hdr shdr;
- u32 status;
- socal_data data;
- u8 xxx1[10];
- u16 ncmds;
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_rsp;
-
-typedef struct {
- socal_hdr shdr;
- u8 xxx1[48];
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_cmdonly;
-
-#define SOCAL_DIAG_NOP 0x00
-#define SOCAL_DIAG_INT_LOOP 0x01
-#define SOCAL_DIAG_EXT_LOOP 0x02
-#define SOCAL_DIAG_REM_LOOP 0x03
-#define SOCAL_DIAG_XRAM_TEST 0x04
-#define SOCAL_DIAG_SOC_TEST 0x05
-#define SOCAL_DIAG_HCB_TEST 0x06
-#define SOCAL_DIAG_SOCLB_TEST 0x07
-#define SOCAL_DIAG_SRDSLB_TEST 0x08
-#define SOCAL_DIAG_EXTOE_TEST 0x09
-
-typedef struct {
- socal_hdr shdr;
- u32 cmd;
- u8 xxx1[44];
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_diag_req;
-
-#define SOCAL_POOL_MASK_RCTL 0x800000
-#define SOCAL_POOL_MASK_DID 0x700000
-#define SOCAL_POOL_MASK_SID 0x070000
-#define SOCAL_POOL_MASK_TYPE 0x008000
-#define SOCAL_POOL_MASK_F_CTL 0x007000
-#define SOCAL_POOL_MASK_SEQ_ID 0x000800
-#define SOCAL_POOL_MASK_D_CTL 0x000400
-#define SOCAL_POOL_MASK_SEQ_CNT 0x000300
-#define SOCAL_POOL_MASK_OX_ID 0x0000f0
-#define SOCAL_POOL_MASK_PARAM 0x00000f
-
-typedef struct {
- socal_hdr shdr;
- u32 pool_id;
- u32 header_mask;
- u32 buf_size;
- u32 entries;
- u8 xxx1[8];
- fc_hdr fchdr;
- u8 count;
- u8 type;
- u8 flags;
- u8 seqno;
-} socal_pool_req;
-
-/* }}} */
-
-/* Now our software structures and constants we use to drive the beast {{{ */
-
-#define SOCAL_CQ_REQ0_SIZE 4
-#define SOCAL_CQ_REQ1_SIZE 256
-#define SOCAL_CQ_RSP0_SIZE 8
-#define SOCAL_CQ_RSP1_SIZE 4
-#define SOCAL_CQ_RSP2_SIZE 4
-
-#define SOCAL_SOLICITED_RSP_Q 0
-#define SOCAL_SOLICITED_BAD_RSP_Q 1
-#define SOCAL_UNSOLICITED_RSP_Q 2
-
-struct socal;
-
-typedef struct {
- /* This must come first */
- fc_channel fc;
- struct socal *s;
- u16 flags;
- u16 mask;
-} socal_port;
-
-typedef struct {
- socal_hw_cq __iomem *hw_cq; /* Related XRAM cq */
- socal_req *pool;
- u8 in;
- u8 out;
- u8 last;
- u8 seqno;
-} socal_cq;
-
-struct socal {
- spinlock_t lock;
- socal_port port[2]; /* Every SOCAL has one or two FC ports */
- socal_cq req[4]; /* Request CQs */
- socal_cq rsp[4]; /* Response CQs */
- int socal_no;
- void __iomem *regs;
- void __iomem *xram;
- void __iomem *eeprom;
- fc_wwn wwn;
- u32 imask; /* Our copy of regs->imask */
- u32 cfg; /* Our copy of regs->cfg */
- char serv_params[80];
- struct socal *next;
- int curr_port; /* Which port will have priority to fcp_queue_empty */
-
- socal_req * req_cpu;
- u32 req_dvma;
-};
-
-/* }}} */
-
-#endif /* !(__SOCAL_H) */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2538816817a..86b8641b466 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2371,13 +2371,16 @@ config UGETH_TX_ON_DEMAND
depends on UCC_GETH
config MV643XX_ETH
- tristate "MV-643XX Ethernet support"
- depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32)
+ tristate "Marvell Discovery (643XX) and Orion ethernet support"
+ depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) || ARCH_ORION
select MII
help
- This driver supports the gigabit Ethernet on the Marvell MV643XX
- chipset which is used in the Momenco Ocelot C and Jaguar ATX and
- Pegasos II, amongst other PPC and MIPS boards.
+ This driver supports the gigabit ethernet MACs in the
+ Marvell Discovery PPC/MIPS chipset family (MV643XX) and
+ in the Marvell Orion ARM SoC family.
+
+ Some boards that use the Discovery chipset are the Momenco
+ Ocelot C and Jaguar ATX and Pegasos II.
config QLA3XXX
tristate "QLogic QLA3XXX Network Driver Support"
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 084f0292ea6..cb3c6faa788 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2076,8 +2076,10 @@ void bond_3ad_unbind_slave(struct slave *slave)
* times out, and it selects an aggregator for the ports that are yet not
* related to any aggregator, and selects the active aggregator for a bond.
*/
-void bond_3ad_state_machine_handler(struct bonding *bond)
+void bond_3ad_state_machine_handler(struct work_struct *work)
{
+ struct bonding *bond = container_of(work, struct bonding,
+ ad_work.work);
struct port *port;
struct aggregator *aggregator;
@@ -2128,7 +2130,7 @@ void bond_3ad_state_machine_handler(struct bonding *bond)
}
re_arm:
- mod_timer(&(BOND_AD_INFO(bond).ad_timer), jiffies + ad_delta_in_ticks);
+ queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
out:
read_unlock(&bond->lock);
}
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index f1655726494..b5ee45f6d55 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -276,7 +276,7 @@ struct ad_slave_info {
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
int bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
-void bond_3ad_state_machine_handler(struct bonding *bond);
+void bond_3ad_state_machine_handler(struct work_struct *);
void bond_3ad_adapter_speed_changed(struct slave *slave);
void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index aea2217c56e..25b8dbf6cfd 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -128,12 +128,12 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
static inline void _lock_tx_hashtbl(struct bonding *bond)
{
- spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+ spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
}
static inline void _unlock_tx_hashtbl(struct bonding *bond)
{
- spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
+ spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
}
/* Caller must hold tx_hashtbl lock */
@@ -305,12 +305,12 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3
/*********************** rlb specific functions ***************************/
static inline void _lock_rx_hashtbl(struct bonding *bond)
{
- spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+ spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
}
static inline void _unlock_rx_hashtbl(struct bonding *bond)
{
- spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
+ spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
}
/* when an ARP REPLY is received from a client update its info
@@ -472,13 +472,13 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
_unlock_rx_hashtbl(bond);
- write_lock(&bond->curr_slave_lock);
+ write_lock_bh(&bond->curr_slave_lock);
if (slave != bond->curr_active_slave) {
rlb_teach_disabled_mac_on_primary(bond, slave->dev->dev_addr);
}
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
}
static void rlb_update_client(struct rlb_client_info *client_info)
@@ -959,19 +959,34 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
return 0;
}
-/* Caller must hold bond lock for write or curr_slave_lock for write*/
+/*
+ * Swap MAC addresses between two slaves.
+ *
+ * Called with RTNL held, and no other locks.
+ *
+ */
+
static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct slave *slave2)
{
- struct slave *disabled_slave = NULL;
u8 tmp_mac_addr[ETH_ALEN];
- int slaves_state_differ;
-
- slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
+}
+
+/*
+ * Send learning packets after MAC address swap.
+ *
+ * Called with RTNL and bond->lock held for read.
+ */
+static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1,
+ struct slave *slave2)
+{
+ int slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
+ struct slave *disabled_slave = NULL;
+
/* fasten the change in the switch */
if (SLAVE_IS_OK(slave1)) {
alb_send_learning_packets(slave1, slave1->dev->dev_addr);
@@ -1044,7 +1059,9 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
}
if (found) {
+ /* locking: needs RTNL and nothing else */
alb_swap_mac_addr(bond, slave, tmp_slave);
+ alb_fasten_mac_swap(bond, slave, tmp_slave);
}
}
}
@@ -1375,8 +1392,10 @@ out:
return 0;
}
-void bond_alb_monitor(struct bonding *bond)
+void bond_alb_monitor(struct work_struct *work)
{
+ struct bonding *bond = container_of(work, struct bonding,
+ alb_work.work);
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct slave *slave;
int i;
@@ -1436,16 +1455,16 @@ void bond_alb_monitor(struct bonding *bond)
/* handle rlb stuff */
if (bond_info->rlb_enabled) {
- /* the following code changes the promiscuity of the
- * the curr_active_slave. It needs to be locked with a
- * write lock to protect from other code that also
- * sets the promiscuity.
- */
- write_lock_bh(&bond->curr_slave_lock);
-
if (bond_info->primary_is_promisc &&
(++bond_info->rlb_promisc_timeout_counter >= RLB_PROMISC_TIMEOUT)) {
+ /*
+ * dev_set_promiscuity requires rtnl and
+ * nothing else.
+ */
+ read_unlock(&bond->lock);
+ rtnl_lock();
+
bond_info->rlb_promisc_timeout_counter = 0;
/* If the primary was set to promiscuous mode
@@ -1454,9 +1473,10 @@ void bond_alb_monitor(struct bonding *bond)
*/
dev_set_promiscuity(bond->curr_active_slave->dev, -1);
bond_info->primary_is_promisc = 0;
- }
- write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
+ read_lock(&bond->lock);
+ }
if (bond_info->rlb_rebalance) {
bond_info->rlb_rebalance = 0;
@@ -1479,7 +1499,7 @@ void bond_alb_monitor(struct bonding *bond)
}
re_arm:
- mod_timer(&(bond_info->alb_timer), jiffies + alb_delta_in_ticks);
+ queue_delayed_work(bond->wq, &bond->alb_work, alb_delta_in_ticks);
out:
read_unlock(&bond->lock);
}
@@ -1500,11 +1520,11 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
/* caller must hold the bond lock for write since the mac addresses
* are compared and may be swapped.
*/
- write_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
res = alb_handle_addr_collision_on_attach(bond, slave);
- write_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
if (res) {
return res;
@@ -1569,13 +1589,21 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char
* Set the bond->curr_active_slave to @new_slave and handle
* mac address swapping and promiscuity changes as needed.
*
- * Caller must hold bond curr_slave_lock for write (or bond lock for write)
+ * If new_slave is NULL, caller must hold curr_slave_lock or
+ * bond->lock for write.
+ *
+ * If new_slave is not NULL, caller must hold RTNL, bond->lock for
+ * read and curr_slave_lock for write. Processing here may sleep, so
+ * no other locks may be held.
*/
void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave)
{
struct slave *swap_slave;
int i;
+ if (new_slave)
+ ASSERT_RTNL();
+
if (bond->curr_active_slave == new_slave) {
return;
}
@@ -1608,6 +1636,19 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
}
}
+ /*
+ * Arrange for swap_slave and new_slave to temporarily be
+ * ignored so we can mess with their MAC addresses without
+ * fear of interference from transmit activity.
+ */
+ if (swap_slave) {
+ tlb_clear_slave(bond, swap_slave, 1);
+ }
+ tlb_clear_slave(bond, new_slave, 1);
+
+ write_unlock_bh(&bond->curr_slave_lock);
+ read_unlock(&bond->lock);
+
/* curr_active_slave must be set before calling alb_swap_mac_addr */
if (swap_slave) {
/* swap mac address */
@@ -1616,11 +1657,23 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
/* set the new_slave to the bond mac address */
alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
bond->alb_info.rlb_enabled);
+ }
+
+ read_lock(&bond->lock);
+
+ if (swap_slave) {
+ alb_fasten_mac_swap(bond, swap_slave, new_slave);
+ } else {
/* fasten bond mac on new current slave */
alb_send_learning_packets(new_slave, bond->dev->dev_addr);
}
+
+ write_lock_bh(&bond->curr_slave_lock);
}
+/*
+ * Called with RTNL
+ */
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
{
struct bonding *bond = bond_dev->priv;
@@ -1657,8 +1710,12 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
}
}
+ write_unlock_bh(&bond->curr_slave_lock);
+ read_unlock(&bond->lock);
+
if (swap_slave) {
alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
+ alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
} else {
alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
bond->alb_info.rlb_enabled);
@@ -1670,6 +1727,9 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
}
}
+ read_lock(&bond->lock);
+ write_lock_bh(&bond->curr_slave_lock);
+
return 0;
}
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index fd872642989..50968f8196c 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -125,7 +125,7 @@ void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave);
void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link);
void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave);
int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
-void bond_alb_monitor(struct bonding *bond);
+void bond_alb_monitor(struct work_struct *);
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
#endif /* __BOND_ALB_H__ */
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6f85cc31f8a..6909becb10f 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1590,15 +1590,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
case BOND_MODE_TLB:
case BOND_MODE_ALB:
new_slave->state = BOND_STATE_ACTIVE;
- if ((!bond->curr_active_slave) &&
- (new_slave->link != BOND_LINK_DOWN)) {
- /* first slave or no active slave yet, and this link
- * is OK, so make this interface the active one
- */
- bond_change_active_slave(bond, new_slave);
- } else {
- bond_set_slave_inactive_flags(new_slave);
- }
+ bond_set_slave_inactive_flags(new_slave);
break;
default:
dprintk("This slave is always active in trunk mode\n");
@@ -1754,9 +1746,23 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
bond_alb_deinit_slave(bond, slave);
}
- if (oldcurrent == slave)
+ if (oldcurrent == slave) {
+ /*
+ * Note that we hold RTNL over this sequence, so there
+ * is no concern that another slave add/remove event
+ * will interfere.
+ */
+ write_unlock_bh(&bond->lock);
+ read_lock(&bond->lock);
+ write_lock_bh(&bond->curr_slave_lock);
+
bond_select_active_slave(bond);
+ write_unlock_bh(&bond->curr_slave_lock);
+ read_unlock(&bond->lock);
+ write_lock_bh(&bond->lock);
+ }
+
if (bond->slave_cnt == 0) {
bond_set_carrier(bond);
@@ -1840,9 +1846,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
*/
void bond_destroy(struct bonding *bond)
{
+ unregister_netdevice(bond->dev);
bond_deinit(bond->dev);
bond_destroy_sysfs_entry(bond);
- unregister_netdevice(bond->dev);
}
/*
@@ -2012,16 +2018,19 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
return -EINVAL;
}
- write_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
+ read_lock(&bond->curr_slave_lock);
old_active = bond->curr_active_slave;
+ read_unlock(&bond->curr_slave_lock);
+
new_active = bond_get_slave_by_dev(bond, slave_dev);
/*
* Changing to the current active: do nothing; return success.
*/
if (new_active && (new_active == old_active)) {
- write_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
return 0;
}
@@ -2029,12 +2038,14 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
(old_active) &&
(new_active->link == BOND_LINK_UP) &&
IS_UP(new_active->dev)) {
+ write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, new_active);
+ write_unlock_bh(&bond->curr_slave_lock);
} else {
res = -EINVAL;
}
- write_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
return res;
}
@@ -2046,9 +2057,9 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
info->bond_mode = bond->params.mode;
info->miimon = bond->params.miimon;
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
info->num_slaves = bond->slave_cnt;
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
return 0;
}
@@ -2063,7 +2074,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
return -ENODEV;
}
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) {
if (i == (int)info->slave_id) {
@@ -2072,7 +2083,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
}
}
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
if (found) {
strcpy(info->slave_name, slave->dev->name);
@@ -2088,26 +2099,25 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
/*-------------------------------- Monitoring -------------------------------*/
-/* this function is called regularly to monitor each slave's link. */
-void bond_mii_monitor(struct net_device *bond_dev)
+/*
+ * if !have_locks, return nonzero if a failover is necessary. if
+ * have_locks, do whatever failover activities are needed.
+ *
+ * This is to separate the inspection and failover steps for locking
+ * purposes; failover requires rtnl, but acquiring it for every
+ * inspection is undesirable, so a wrapper first does inspection, and
+ * the acquires the necessary locks and calls again to perform
+ * failover if needed. Since all locks are dropped, a complete
+ * restart is needed between calls.
+ */
+static int __bond_mii_monitor(struct bonding *bond, int have_locks)
{
- struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
int do_failover = 0;
- int delta_in_ticks;
int i;
- read_lock(&bond->lock);
-
- delta_in_ticks = (bond->params.miimon * HZ) / 1000;
-
- if (bond->kill_timers) {
+ if (bond->slave_cnt == 0)
goto out;
- }
-
- if (bond->slave_cnt == 0) {
- goto re_arm;
- }
/* we will try to read the link status of each of our slaves, and
* set their IFF_RUNNING flag appropriately. For each slave not
@@ -2141,7 +2151,11 @@ void bond_mii_monitor(struct net_device *bond_dev)
switch (slave->link) {
case BOND_LINK_UP: /* the link was up */
if (link_state == BMSR_LSTATUS) {
- /* link stays up, nothing more to do */
+ if (!oldcurrent) {
+ if (!have_locks)
+ return 1;
+ do_failover = 1;
+ }
break;
} else { /* link going down */
slave->link = BOND_LINK_FAIL;
@@ -2156,7 +2170,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
": %s: link status down for %s "
"interface %s, disabling it in "
"%d ms.\n",
- bond_dev->name,
+ bond->dev->name,
IS_UP(slave_dev)
? ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
? ((slave == oldcurrent)
@@ -2174,6 +2188,9 @@ void bond_mii_monitor(struct net_device *bond_dev)
if (link_state != BMSR_LSTATUS) {
/* link stays down */
if (slave->delay <= 0) {
+ if (!have_locks)
+ return 1;
+
/* link down for too long time */
slave->link = BOND_LINK_DOWN;
@@ -2189,7 +2206,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
": %s: link status definitely "
"down for interface %s, "
"disabling it\n",
- bond_dev->name,
+ bond->dev->name,
slave_dev->name);
/* notify ad that the link status has changed */
@@ -2215,7 +2232,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status up again after %d "
"ms for interface %s.\n",
- bond_dev->name,
+ bond->dev->name,
(bond->params.downdelay - slave->delay) * bond->params.miimon,
slave_dev->name);
}
@@ -2235,7 +2252,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
": %s: link status up for "
"interface %s, enabling it "
"in %d ms.\n",
- bond_dev->name,
+ bond->dev->name,
slave_dev->name,
bond->params.updelay * bond->params.miimon);
}
@@ -2251,12 +2268,15 @@ void bond_mii_monitor(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status down again after %d "
"ms for interface %s.\n",
- bond_dev->name,
+ bond->dev->name,
(bond->params.updelay - slave->delay) * bond->params.miimon,
slave_dev->name);
} else {
/* link stays up */
if (slave->delay == 0) {
+ if (!have_locks)
+ return 1;
+
/* now the link has been up for long time enough */
slave->link = BOND_LINK_UP;
slave->jiffies = jiffies;
@@ -2275,7 +2295,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status definitely "
"up for interface %s.\n",
- bond_dev->name,
+ bond->dev->name,
slave_dev->name);
/* notify ad that the link status has changed */
@@ -2301,7 +2321,7 @@ void bond_mii_monitor(struct net_device *bond_dev)
/* Should not happen */
printk(KERN_ERR DRV_NAME
": %s: Error: %s Illegal value (link=%d)\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name,
slave->link);
goto out;
@@ -2322,22 +2342,52 @@ void bond_mii_monitor(struct net_device *bond_dev)
} /* end of for */
if (do_failover) {
- write_lock(&bond->curr_slave_lock);
+ ASSERT_RTNL();
+
+ write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+
} else
bond_set_carrier(bond);
-re_arm:
- if (bond->params.miimon) {
- mod_timer(&bond->mii_timer, jiffies + delta_in_ticks);
- }
out:
- read_unlock(&bond->lock);
+ return 0;
}
+/*
+ * bond_mii_monitor
+ *
+ * Really a wrapper that splits the mii monitor into two phases: an
+ * inspection, then (if inspection indicates something needs to be
+ * done) an acquisition of appropriate locks followed by another pass
+ * to implement whatever link state changes are indicated.
+ */
+void bond_mii_monitor(struct work_struct *work)
+{
+ struct bonding *bond = container_of(work, struct bonding,
+ mii_work.work);
+ unsigned long delay;
+
+ read_lock(&bond->lock);
+ if (bond->kill_timers) {
+ read_unlock(&bond->lock);
+ return;
+ }
+ if (__bond_mii_monitor(bond, 0)) {
+ read_unlock(&bond->lock);
+ rtnl_lock();
+ read_lock(&bond->lock);
+ __bond_mii_monitor(bond, 1);
+ rtnl_unlock();
+ }
+
+ delay = ((bond->params.miimon * HZ) / 1000) ? : 1;
+ read_unlock(&bond->lock);
+ queue_delayed_work(bond->wq, &bond->mii_work, delay);
+}
static __be32 bond_glean_dev_ip(struct net_device *dev)
{
@@ -2636,9 +2686,10 @@ out:
* arp is transmitted to generate traffic. see activebackup_arp_monitor for
* arp monitoring in active backup mode.
*/
-void bond_loadbalance_arp_mon(struct net_device *bond_dev)
+void bond_loadbalance_arp_mon(struct work_struct *work)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = container_of(work, struct bonding,
+ arp_work.work);
struct slave *slave, *oldcurrent;
int do_failover = 0;
int delta_in_ticks;
@@ -2685,13 +2736,13 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status definitely "
"up for interface %s, ",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
do_failover = 1;
} else {
printk(KERN_INFO DRV_NAME
": %s: interface %s is now up\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
}
}
@@ -2715,7 +2766,7 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: interface %s is now down.\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
if (slave == oldcurrent) {
@@ -2737,17 +2788,19 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev)
}
if (do_failover) {
- write_lock(&bond->curr_slave_lock);
+ rtnl_lock();
+ write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
+
}
re_arm:
- if (bond->params.arp_interval) {
- mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
- }
+ if (bond->params.arp_interval)
+ queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
out:
read_unlock(&bond->lock);
}
@@ -2767,9 +2820,10 @@ out:
* may have received.
* see loadbalance_arp_monitor for arp monitoring in load balancing mode
*/
-void bond_activebackup_arp_mon(struct net_device *bond_dev)
+void bond_activebackup_arp_mon(struct work_struct *work)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = container_of(work, struct bonding,
+ arp_work.work);
struct slave *slave;
int delta_in_ticks;
int i;
@@ -2798,7 +2852,9 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
slave->link = BOND_LINK_UP;
- write_lock(&bond->curr_slave_lock);
+ rtnl_lock();
+
+ write_lock_bh(&bond->curr_slave_lock);
if ((!bond->curr_active_slave) &&
((jiffies - slave->dev->trans_start) <= delta_in_ticks)) {
@@ -2821,18 +2877,19 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: %s is up and now the "
"active interface\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
netif_carrier_on(bond->dev);
} else {
printk(KERN_INFO DRV_NAME
": %s: backup interface %s is "
"now up\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
}
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+ rtnl_unlock();
}
} else {
read_lock(&bond->curr_slave_lock);
@@ -2864,7 +2921,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: backup interface %s is now down\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
} else {
read_unlock(&bond->curr_slave_lock);
@@ -2899,15 +2956,18 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: link status down for active interface "
"%s, disabling it\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
- write_lock(&bond->curr_slave_lock);
+ rtnl_lock();
+ write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond);
slave = bond->curr_active_slave;
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+
+ rtnl_unlock();
bond->current_arp_slave = slave;
@@ -2921,14 +2981,17 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: changing from interface %s to primary "
"interface %s\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name,
bond->primary_slave->dev->name);
/* primary is up so switch to it */
- write_lock(&bond->curr_slave_lock);
+ rtnl_lock();
+ write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, bond->primary_slave);
- write_unlock(&bond->curr_slave_lock);
+ write_unlock_bh(&bond->curr_slave_lock);
+
+ rtnl_unlock();
slave = bond->primary_slave;
slave->jiffies = jiffies;
@@ -2985,7 +3048,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
printk(KERN_INFO DRV_NAME
": %s: backup interface %s is "
"now down.\n",
- bond_dev->name,
+ bond->dev->name,
slave->dev->name);
}
}
@@ -2994,7 +3057,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
re_arm:
if (bond->params.arp_interval) {
- mod_timer(&bond->arp_timer, jiffies + delta_in_ticks);
+ queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
}
out:
read_unlock(&bond->lock);
@@ -3015,7 +3078,7 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
/* make sure the bond won't be taken away */
read_lock(&dev_base_lock);
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
if (*pos == 0) {
return SEQ_START_TOKEN;
@@ -3049,7 +3112,7 @@ static void bond_info_seq_stop(struct seq_file *seq, void *v)
{
struct bonding *bond = seq->private;
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
read_unlock(&dev_base_lock);
}
@@ -3582,15 +3645,11 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb,
static int bond_open(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
- struct timer_list *mii_timer = &bond->mii_timer;
- struct timer_list *arp_timer = &bond->arp_timer;
bond->kill_timers = 0;
if ((bond->params.mode == BOND_MODE_TLB) ||
(bond->params.mode == BOND_MODE_ALB)) {
- struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer);
-
/* bond_alb_initialize must be called before the timer
* is started.
*/
@@ -3599,44 +3658,31 @@ static int bond_open(struct net_device *bond_dev)
return -1;
}
- init_timer(alb_timer);
- alb_timer->expires = jiffies + 1;
- alb_timer->data = (unsigned long)bond;
- alb_timer->function = (void *)&bond_alb_monitor;
- add_timer(alb_timer);
+ INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
+ queue_delayed_work(bond->wq, &bond->alb_work, 0);
}
if (bond->params.miimon) { /* link check interval, in milliseconds. */
- init_timer(mii_timer);
- mii_timer->expires = jiffies + 1;
- mii_timer->data = (unsigned long)bond_dev;
- mii_timer->function = (void *)&bond_mii_monitor;
- add_timer(mii_timer);
+ INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+ queue_delayed_work(bond->wq, &bond->mii_work, 0);
}
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- init_timer(arp_timer);
- arp_timer->expires = jiffies + 1;
- arp_timer->data = (unsigned long)bond_dev;
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
- arp_timer->function = (void *)&bond_activebackup_arp_mon;
- } else {
- arp_timer->function = (void *)&bond_loadbalance_arp_mon;
- }
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ INIT_DELAYED_WORK(&bond->arp_work,
+ bond_activebackup_arp_mon);
+ else
+ INIT_DELAYED_WORK(&bond->arp_work,
+ bond_loadbalance_arp_mon);
+
+ queue_delayed_work(bond->wq, &bond->arp_work, 0);
if (bond->params.arp_validate)
bond_register_arp(bond);
-
- add_timer(arp_timer);
}
if (bond->params.mode == BOND_MODE_8023AD) {
- struct timer_list *ad_timer = &(BOND_AD_INFO(bond).ad_timer);
- init_timer(ad_timer);
- ad_timer->expires = jiffies + 1;
- ad_timer->data = (unsigned long)bond;
- ad_timer->function = (void *)&bond_3ad_state_machine_handler;
- add_timer(ad_timer);
-
+ INIT_DELAYED_WORK(&bond->ad_work, bond_alb_monitor);
+ queue_delayed_work(bond->wq, &bond->ad_work, 0);
/* register to receive LACPDUs */
bond_register_lacpdu(bond);
}
@@ -3664,25 +3710,21 @@ static int bond_close(struct net_device *bond_dev)
write_unlock_bh(&bond->lock);
- /* del_timer_sync must run without holding the bond->lock
- * because a running timer might be trying to hold it too
- */
-
if (bond->params.miimon) { /* link check interval, in milliseconds. */
- del_timer_sync(&bond->mii_timer);
+ cancel_delayed_work(&bond->mii_work);
}
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- del_timer_sync(&bond->arp_timer);
+ cancel_delayed_work(&bond->arp_work);
}
switch (bond->params.mode) {
case BOND_MODE_8023AD:
- del_timer_sync(&(BOND_AD_INFO(bond).ad_timer));
+ cancel_delayed_work(&bond->ad_work);
break;
case BOND_MODE_TLB:
case BOND_MODE_ALB:
- del_timer_sync(&(BOND_ALB_INFO(bond).alb_timer));
+ cancel_delayed_work(&bond->alb_work);
break;
default:
break;
@@ -3779,13 +3821,13 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
if (mii->reg_num == 1) {
struct bonding *bond = bond_dev->priv;
mii->val_out = 0;
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
read_lock(&bond->curr_slave_lock);
if (netif_carrier_ok(bond->dev)) {
mii->val_out = BMSR_LSTATUS;
}
read_unlock(&bond->curr_slave_lock);
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
}
return 0;
@@ -4077,8 +4119,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *start_at;
- int i;
- int res = 1;
+ int i, slave_no, res = 1;
read_lock(&bond->lock);
@@ -4086,29 +4127,29 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
goto out;
}
- read_lock(&bond->curr_slave_lock);
- slave = start_at = bond->curr_active_slave;
- read_unlock(&bond->curr_slave_lock);
+ /*
+ * Concurrent TX may collide on rr_tx_counter; we accept that
+ * as being rare enough not to justify using an atomic op here
+ */
+ slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
- if (!slave) {
- goto out;
+ bond_for_each_slave(bond, slave, i) {
+ slave_no--;
+ if (slave_no < 0) {
+ break;
+ }
}
+ start_at = slave;
bond_for_each_slave_from(bond, slave, i, start_at) {
if (IS_UP(slave->dev) &&
(slave->link == BOND_LINK_UP) &&
(slave->state == BOND_STATE_ACTIVE)) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
-
- write_lock(&bond->curr_slave_lock);
- bond->curr_active_slave = slave->next;
- write_unlock(&bond->curr_slave_lock);
-
break;
}
}
-
out:
if (res) {
/* no suitable interface, frame not sent */
@@ -4340,6 +4381,10 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
bond->params = *params; /* copy params struct */
+ bond->wq = create_singlethread_workqueue(bond_dev->name);
+ if (!bond->wq)
+ return -ENOMEM;
+
/* Initialize pointers */
bond->first_slave = NULL;
bond->curr_active_slave = NULL;
@@ -4428,8 +4473,8 @@ static void bond_free_all(void)
bond_mc_list_destroy(bond);
/* Release the bonded slaves */
bond_release_all(bond_dev);
- bond_deinit(bond_dev);
unregister_netdevice(bond_dev);
+ bond_deinit(bond_dev);
}
#ifdef CONFIG_PROC_FS
@@ -4826,10 +4871,32 @@ out_rtnl:
return res;
}
+static void bond_work_cancel_all(struct bonding *bond)
+{
+ write_lock_bh(&bond->lock);
+ bond->kill_timers = 1;
+ write_unlock_bh(&bond->lock);
+
+ if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
+ cancel_delayed_work(&bond->mii_work);
+
+ if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
+ cancel_delayed_work(&bond->arp_work);
+
+ if (bond->params.mode == BOND_MODE_ALB &&
+ delayed_work_pending(&bond->alb_work))
+ cancel_delayed_work(&bond->alb_work);
+
+ if (bond->params.mode == BOND_MODE_8023AD &&
+ delayed_work_pending(&bond->ad_work))
+ cancel_delayed_work(&bond->ad_work);
+}
+
static int __init bonding_init(void)
{
int i;
int res;
+ struct bonding *bond, *nxt;
printk(KERN_INFO "%s", version);
@@ -4856,6 +4923,11 @@ static int __init bonding_init(void)
goto out;
err:
+ list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
+ bond_work_cancel_all(bond);
+ destroy_workqueue(bond->wq);
+ }
+
rtnl_lock();
bond_free_all();
bond_destroy_sysfs();
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 855dc10ffa1..7a06ade85b0 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -229,7 +229,7 @@ static ssize_t bonding_show_slaves(struct device *d,
int i, res = 0;
struct bonding *bond = to_bond(d);
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) {
if (res > (PAGE_SIZE - IFNAMSIZ)) {
/* not enough space for another interface name */
@@ -240,7 +240,7 @@ static ssize_t bonding_show_slaves(struct device *d,
}
res += sprintf(buf + res, "%s ", slave->dev->name);
}
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
res += sprintf(buf + res, "\n");
res++;
return res;
@@ -282,18 +282,18 @@ static ssize_t bonding_store_slaves(struct device *d,
/* Got a slave name in ifname. Is it already in the list? */
found = 0;
- read_lock_bh(&bond->lock);
+ read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i)
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
printk(KERN_ERR DRV_NAME
": %s: Interface %s is already enslaved!\n",
bond->dev->name, ifname);
ret = -EPERM;
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
goto out;
}
- read_unlock_bh(&bond->lock);
+ read_unlock(&bond->lock);
printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
bond->dev->name, ifname);
dev = dev_get_by_name(&init_net, ifname);
@@ -662,12 +662,9 @@ static ssize_t bonding_store_arp_interval(struct device *d,
"%s Disabling MII monitoring.\n",
bond->dev->name, bond->dev->name);
bond->params.miimon = 0;
- /* Kill MII timer, else it brings bond's link down */
- if (bond->arp_timer.function) {
- printk(KERN_INFO DRV_NAME
- ": %s: Kill MII timer, else it brings bond's link down...\n",
- bond->dev->name);
- del_timer_sync(&bond->mii_timer);
+ if (delayed_work_pending(&bond->mii_work)) {
+ cancel_delayed_work(&bond->mii_work);
+ flush_workqueue(bond->wq);
}
}
if (!bond->params.arp_targets[0]) {
@@ -682,25 +679,15 @@ static ssize_t bonding_store_arp_interval(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- if (bond->arp_timer.function) {
- /* The timer's already set up, so fire it off */
- mod_timer(&bond->arp_timer, jiffies + 1);
- } else {
- /* Set up the timer. */
- init_timer(&bond->arp_timer);
- bond->arp_timer.expires = jiffies + 1;
- bond->arp_timer.data =
- (unsigned long) bond->dev;
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
- bond->arp_timer.function =
- (void *)
- &bond_activebackup_arp_mon;
- } else {
- bond->arp_timer.function =
- (void *)
- &bond_loadbalance_arp_mon;
- }
- add_timer(&bond->arp_timer);
+ if (!delayed_work_pending(&bond->arp_work)) {
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ INIT_DELAYED_WORK(&bond->arp_work,
+ bond_activebackup_arp_mon);
+ else
+ INIT_DELAYED_WORK(&bond->arp_work,
+ bond_loadbalance_arp_mon);
+
+ queue_delayed_work(bond->wq, &bond->arp_work, 0);
}
}
@@ -1056,12 +1043,9 @@ static ssize_t bonding_store_miimon(struct device *d,
bond->params.arp_validate =
BOND_ARP_VALIDATE_NONE;
}
- /* Kill ARP timer, else it brings bond's link down */
- if (bond->mii_timer.function) {
- printk(KERN_INFO DRV_NAME
- ": %s: Kill ARP timer, else it brings bond's link down...\n",
- bond->dev->name);
- del_timer_sync(&bond->arp_timer);
+ if (delayed_work_pending(&bond->arp_work)) {
+ cancel_delayed_work(&bond->arp_work);
+ flush_workqueue(bond->wq);
}
}
@@ -1071,18 +1055,11 @@ static ssize_t bonding_store_miimon(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- if (bond->mii_timer.function) {
- /* The timer's already set up, so fire it off */
- mod_timer(&bond->mii_timer, jiffies + 1);
- } else {
- /* Set up the timer. */
- init_timer(&bond->mii_timer);
- bond->mii_timer.expires = jiffies + 1;
- bond->mii_timer.data =
- (unsigned long) bond->dev;
- bond->mii_timer.function =
- (void *) &bond_mii_monitor;
- add_timer(&bond->mii_timer);
+ if (!delayed_work_pending(&bond->mii_work)) {
+ INIT_DELAYED_WORK(&bond->mii_work,
+ bond_mii_monitor);
+ queue_delayed_work(bond->wq,
+ &bond->mii_work, 0);
}
}
}
@@ -1156,6 +1133,9 @@ static ssize_t bonding_store_primary(struct device *d,
}
out:
write_unlock_bh(&bond->lock);
+
+ rtnl_unlock();
+
return count;
}
static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
@@ -1213,6 +1193,7 @@ static ssize_t bonding_show_active_slave(struct device *d,
struct bonding *bond = to_bond(d);
int count;
+ rtnl_lock();
read_lock(&bond->curr_slave_lock);
curr = bond->curr_active_slave;
@@ -1292,6 +1273,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
}
out:
write_unlock_bh(&bond->lock);
+ rtnl_unlock();
+
return count;
}
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index b8180600a30..d1ed14bf1cc 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -184,8 +184,6 @@ struct bonding {
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
rwlock_t lock;
rwlock_t curr_slave_lock;
- struct timer_list mii_timer;
- struct timer_list arp_timer;
s8 kill_timers;
s8 send_grat_arp;
s8 setup_by_slave;
@@ -199,12 +197,18 @@ struct bonding {
int (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int);
__be32 master_ip;
u16 flags;
+ u16 rr_tx_counter;
struct ad_bond_info ad_info;
struct alb_bond_info alb_info;
struct bond_params params;
struct list_head vlan_list;
struct vlan_group *vlgrp;
struct packet_type arp_mon_pt;
+ struct workqueue_struct *wq;
+ struct delayed_work mii_work;
+ struct delayed_work arp_work;
+ struct delayed_work alb_work;
+ struct delayed_work ad_work;
};
/**
@@ -307,9 +311,9 @@ int bond_create_slave_symlinks(struct net_device *master, struct net_device *sla
void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
-void bond_mii_monitor(struct net_device *bond_dev);
-void bond_loadbalance_arp_mon(struct net_device *bond_dev);
-void bond_activebackup_arp_mon(struct net_device *bond_dev);
+void bond_mii_monitor(struct work_struct *);
+void bond_loadbalance_arp_mon(struct work_struct *);
+void bond_activebackup_arp_mon(struct work_struct *);
void bond_set_mode_ops(struct bonding *bond, int mode);
int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
void bond_select_active_slave(struct bonding *bond);
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index ae419736158..57541d2d9e1 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -460,18 +460,11 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct cpmac_desc *desc;
struct cpmac_priv *priv = netdev_priv(dev);
- if (unlikely(skb_padto(skb, ETH_ZLEN))) {
- if (netif_msg_tx_err(priv) && net_ratelimit())
- printk(KERN_WARNING
- "%s: tx: padding failed, dropping\n", dev->name);
- spin_lock(&priv->lock);
- dev->stats.tx_dropped++;
- spin_unlock(&priv->lock);
- return -ENOMEM;
- }
+ if (unlikely(skb_padto(skb, ETH_ZLEN)))
+ return NETDEV_TX_OK;
len = max(skb->len, ETH_ZLEN);
- queue = skb_get_queue_mapping(skb);
+ queue = skb->queue_mapping;
#ifdef CONFIG_NETDEVICES_MULTIQUEUE
netif_stop_subqueue(dev, queue);
#else
@@ -481,13 +474,9 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
desc = &priv->desc_ring[queue];
if (unlikely(desc->dataflags & CPMAC_OWN)) {
if (netif_msg_tx_err(priv) && net_ratelimit())
- printk(KERN_WARNING "%s: tx dma ring full, dropping\n",
+ printk(KERN_WARNING "%s: tx dma ring full\n",
dev->name);
- spin_lock(&priv->lock);
- dev->stats.tx_dropped++;
- spin_unlock(&priv->lock);
- dev_kfree_skb_any(skb);
- return -ENOMEM;
+ return NETDEV_TX_BUSY;
}
spin_lock(&priv->lock);
@@ -509,7 +498,7 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
cpmac_dump_skb(dev, skb);
cpmac_write(priv->regs, CPMAC_TX_PTR(queue), (u32)desc->mapping);
- return 0;
+ return NETDEV_TX_OK;
}
static void cpmac_end_xmit(struct net_device *dev, int queue)
@@ -646,12 +635,14 @@ static void cpmac_clear_tx(struct net_device *dev)
int i;
if (unlikely(!priv->desc_ring))
return;
- for (i = 0; i < CPMAC_QUEUES; i++)
+ for (i = 0; i < CPMAC_QUEUES; i++) {
+ priv->desc_ring[i].dataflags = 0;
if (priv->desc_ring[i].skb) {
dev_kfree_skb_any(priv->desc_ring[i].skb);
if (netif_subqueue_stopped(dev, i))
netif_wake_subqueue(dev, i);
}
+ }
}
static void cpmac_hw_error(struct work_struct *work)
@@ -727,11 +718,13 @@ static void cpmac_tx_timeout(struct net_device *dev)
#ifdef CONFIG_NETDEVICES_MULTIQUEUE
for (i = 0; i < CPMAC_QUEUES; i++)
if (priv->desc_ring[i].skb) {
+ priv->desc_ring[i].dataflags = 0;
dev_kfree_skb_any(priv->desc_ring[i].skb);
netif_wake_subqueue(dev, i);
break;
}
#else
+ priv->desc_ring[0].dataflags = 0;
if (priv->desc_ring[0].skb)
dev_kfree_skb_any(priv->desc_ring[0].skb);
netif_wake_queue(dev);
@@ -794,7 +787,7 @@ static int cpmac_set_ringparam(struct net_device *dev, struct ethtool_ringparam*
{
struct cpmac_priv *priv = netdev_priv(dev);
- if (dev->flags && IFF_UP)
+ if (netif_running(dev))
return -EBUSY;
priv->ring_size = ring->rx_pending;
return 0;
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index b07613e61f5..ddc30c4bf34 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -805,7 +805,7 @@ static void __devinit dfx_bus_init(struct net_device *dev)
* Interrupts are disabled at the adapter bus-specific logic.
*/
-static void __devinit dfx_bus_uninit(struct net_device *dev)
+static void __devexit dfx_bus_uninit(struct net_device *dev)
{
DFX_board_t *bp = netdev_priv(dev);
struct device *bdev = bp->bus_dev;
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 9c85e50014b..70509ed6c11 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -651,9 +651,9 @@ static void eexp_timeout(struct net_device *dev)
*/
static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
{
- struct net_local *lp = netdev_priv(dev);
short length = buf->len;
#ifdef CONFIG_SMP
+ struct net_local *lp = netdev_priv(dev);
unsigned long flags;
#endif
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 37707a0c049..aafc3ce59cb 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -30,6 +30,7 @@ static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
int len)
{
uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
+
if (available_len < len)
return -EFAULT;
@@ -45,14 +46,8 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
int count_to_go = skb->len;
char *buf_ptr = skb->data;
- pr_debug("%s: %s(): telling MIPSNET txDataCount(%d)\n",
- dev->name, __FUNCTION__, skb->len);
-
outl(skb->len, mipsnet_reg_address(dev, txDataCount));
- pr_debug("%s: %s(): sending data to MIPSNET txDataBuffer(%d)\n",
- dev->name, __FUNCTION__, skb->len);
-
for (; count_to_go; buf_ptr++, count_to_go--)
outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
@@ -64,10 +59,8 @@ static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
- pr_debug("%s:%s(): transmitting %d bytes\n",
- dev->name, __FUNCTION__, skb->len);
-
- /* Only one packet at a time. Once TXDONE interrupt is serviced, the
+ /*
+ * Only one packet at a time. Once TXDONE interrupt is serviced, the
* queue will be restarted.
*/
netif_stop_queue(dev);
@@ -94,8 +87,6 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
- pr_debug("%s:%s(): pushing RXed data to kernel\n",
- dev->name, __FUNCTION__);
netif_rx(skb);
dev->stats.rx_packets++;
@@ -112,44 +103,29 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
uint64_t interruptFlags;
if (irq == dev->irq) {
- pr_debug("%s:%s(): irq %d for device\n",
- dev->name, __FUNCTION__, irq);
-
retval = IRQ_HANDLED;
interruptFlags =
inl(mipsnet_reg_address(dev, interruptControl));
- pr_debug("%s:%s(): intCtl=0x%016llx\n", dev->name,
- __FUNCTION__, interruptFlags);
if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
- pr_debug("%s:%s(): got TXDone\n",
- dev->name, __FUNCTION__);
outl(MIPSNET_INTCTL_TXDONE,
mipsnet_reg_address(dev, interruptControl));
/* only one packet at a time, we are done. */
netif_wake_queue(dev);
} else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
- pr_debug("%s:%s(): got RX data\n",
- dev->name, __FUNCTION__);
mipsnet_get_fromdev(dev,
inl(mipsnet_reg_address(dev, rxDataCount)));
- pr_debug("%s:%s(): clearing RX int\n",
- dev->name, __FUNCTION__);
outl(MIPSNET_INTCTL_RXDONE,
mipsnet_reg_address(dev, interruptControl));
} else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
- pr_debug("%s:%s(): got test interrupt\n",
- dev->name, __FUNCTION__);
/*
* TESTBIT is cleared on read.
* And takes effect after a write with 0
*/
outl(0, mipsnet_reg_address(dev, interruptControl));
} else {
- pr_debug("%s:%s(): no valid fags 0x%016llx\n",
- dev->name, __FUNCTION__, interruptFlags);
/* Maybe shared IRQ, just ignore, no clearing. */
retval = IRQ_NONE;
}
@@ -165,22 +141,15 @@ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
static int mipsnet_open(struct net_device *dev)
{
int err;
- pr_debug("%s: mipsnet_open\n", dev->name);
err = request_irq(dev->irq, &mipsnet_interrupt,
IRQF_SHARED, dev->name, (void *) dev);
if (err) {
- pr_debug("%s: %s(): can't get irq %d\n",
- dev->name, __FUNCTION__, dev->irq);
release_region(dev->base_addr, MIPSNET_IO_EXTENT);
return err;
}
- pr_debug("%s: %s(): got IO region at 0x%04lx and irq %d for dev.\n",
- dev->name, __FUNCTION__, dev->base_addr, dev->irq);
-
-
netif_start_queue(dev);
/* test interrupt handler */
@@ -193,8 +162,8 @@ static int mipsnet_open(struct net_device *dev)
static int mipsnet_close(struct net_device *dev)
{
- pr_debug("%s: %s()\n", dev->name, __FUNCTION__);
netif_stop_queue(dev);
+
return 0;
}
@@ -229,9 +198,6 @@ static int __init mipsnet_probe(struct device *dev)
/* Get the io region now, get irq on open() */
if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
- pr_debug("%s: %s(): IO region {start: 0x%04lux, len: %d} "
- "for dev is not availble.\n", netdev->name,
- __FUNCTION__, netdev->base_addr, MIPSNET_IO_EXTENT);
err = -EBUSY;
goto out_free_netdev;
}
@@ -295,8 +261,6 @@ static int __init mipsnet_init_module(void)
static void __exit mipsnet_exit_module(void)
{
- pr_debug("MIPSNet Ethernet driver exiting\n");
-
driver_unregister(&mipsnet_driver);
}
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 84f2d6382f1..651c2699d5e 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/mv643xx_eth.c - Driver for MV643XX ethernet ports
+ * Driver for Marvell Discovery (MV643XX) and Marvell Orion ethernet ports
* Copyright (C) 2002 Matthew Dharm <mdharm@momenco.com>
*
* Based on the 64360 driver from:
@@ -43,14 +43,567 @@
#include <linux/ethtool.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+
+#include <linux/mv643xx_eth.h>
+
#include <asm/io.h>
#include <asm/types.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/delay.h>
-#include "mv643xx_eth.h"
+#include <asm/dma-mapping.h>
+
+#define MV643XX_CHECKSUM_OFFLOAD_TX
+#define MV643XX_NAPI
+#define MV643XX_TX_FAST_REFILL
+#undef MV643XX_COAL
+
+/*
+ * Number of RX / TX descriptors on RX / TX rings.
+ * Note that allocating RX descriptors is done by allocating the RX
+ * ring AND a preallocated RX buffers (skb's) for each descriptor.
+ * The TX descriptors only allocates the TX descriptors ring,
+ * with no pre allocated TX buffers (skb's are allocated by higher layers.
+ */
+
+/* Default TX ring size is 1000 descriptors */
+#define MV643XX_DEFAULT_TX_QUEUE_SIZE 1000
+
+/* Default RX ring size is 400 descriptors */
+#define MV643XX_DEFAULT_RX_QUEUE_SIZE 400
+
+#define MV643XX_TX_COAL 100
+#ifdef MV643XX_COAL
+#define MV643XX_RX_COAL 100
+#endif
+
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
+#else
+#define MAX_DESCS_PER_SKB 1
+#endif
+
+#define ETH_VLAN_HLEN 4
+#define ETH_FCS_LEN 4
+#define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */
+#define ETH_WRAPPER_LEN (ETH_HW_IP_ALIGN + ETH_HLEN + \
+ ETH_VLAN_HLEN + ETH_FCS_LEN)
+#define ETH_RX_SKB_SIZE (dev->mtu + ETH_WRAPPER_LEN + \
+ dma_get_cache_alignment())
+
+/*
+ * Registers shared between all ports.
+ */
+#define PHY_ADDR_REG 0x0000
+#define SMI_REG 0x0004
+
+/*
+ * Per-port registers.
+ */
+#define PORT_CONFIG_REG(p) (0x0400 + ((p) << 10))
+#define PORT_CONFIG_EXTEND_REG(p) (0x0404 + ((p) << 10))
+#define MAC_ADDR_LOW(p) (0x0414 + ((p) << 10))
+#define MAC_ADDR_HIGH(p) (0x0418 + ((p) << 10))
+#define SDMA_CONFIG_REG(p) (0x041c + ((p) << 10))
+#define PORT_SERIAL_CONTROL_REG(p) (0x043c + ((p) << 10))
+#define PORT_STATUS_REG(p) (0x0444 + ((p) << 10))
+#define TRANSMIT_QUEUE_COMMAND_REG(p) (0x0448 + ((p) << 10))
+#define MAXIMUM_TRANSMIT_UNIT(p) (0x0458 + ((p) << 10))
+#define INTERRUPT_CAUSE_REG(p) (0x0460 + ((p) << 10))
+#define INTERRUPT_CAUSE_EXTEND_REG(p) (0x0464 + ((p) << 10))
+#define INTERRUPT_MASK_REG(p) (0x0468 + ((p) << 10))
+#define INTERRUPT_EXTEND_MASK_REG(p) (0x046c + ((p) << 10))
+#define TX_FIFO_URGENT_THRESHOLD_REG(p) (0x0474 + ((p) << 10))
+#define RX_CURRENT_QUEUE_DESC_PTR_0(p) (0x060c + ((p) << 10))
+#define RECEIVE_QUEUE_COMMAND_REG(p) (0x0680 + ((p) << 10))
+#define TX_CURRENT_QUEUE_DESC_PTR_0(p) (0x06c0 + ((p) << 10))
+#define MIB_COUNTERS_BASE(p) (0x1000 + ((p) << 7))
+#define DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(p) (0x1400 + ((p) << 10))
+#define DA_FILTER_OTHER_MULTICAST_TABLE_BASE(p) (0x1500 + ((p) << 10))
+#define DA_FILTER_UNICAST_TABLE_BASE(p) (0x1600 + ((p) << 10))
+
+/* These macros describe Ethernet Port configuration reg (Px_cR) bits */
+#define UNICAST_NORMAL_MODE (0 << 0)
+#define UNICAST_PROMISCUOUS_MODE (1 << 0)
+#define DEFAULT_RX_QUEUE(queue) ((queue) << 1)
+#define DEFAULT_RX_ARP_QUEUE(queue) ((queue) << 4)
+#define RECEIVE_BC_IF_NOT_IP_OR_ARP (0 << 7)
+#define REJECT_BC_IF_NOT_IP_OR_ARP (1 << 7)
+#define RECEIVE_BC_IF_IP (0 << 8)
+#define REJECT_BC_IF_IP (1 << 8)
+#define RECEIVE_BC_IF_ARP (0 << 9)
+#define REJECT_BC_IF_ARP (1 << 9)
+#define TX_AM_NO_UPDATE_ERROR_SUMMARY (1 << 12)
+#define CAPTURE_TCP_FRAMES_DIS (0 << 14)
+#define CAPTURE_TCP_FRAMES_EN (1 << 14)
+#define CAPTURE_UDP_FRAMES_DIS (0 << 15)
+#define CAPTURE_UDP_FRAMES_EN (1 << 15)
+#define DEFAULT_RX_TCP_QUEUE(queue) ((queue) << 16)
+#define DEFAULT_RX_UDP_QUEUE(queue) ((queue) << 19)
+#define DEFAULT_RX_BPDU_QUEUE(queue) ((queue) << 22)
+
+#define PORT_CONFIG_DEFAULT_VALUE \
+ UNICAST_NORMAL_MODE | \
+ DEFAULT_RX_QUEUE(0) | \
+ DEFAULT_RX_ARP_QUEUE(0) | \
+ RECEIVE_BC_IF_NOT_IP_OR_ARP | \
+ RECEIVE_BC_IF_IP | \
+ RECEIVE_BC_IF_ARP | \
+ CAPTURE_TCP_FRAMES_DIS | \
+ CAPTURE_UDP_FRAMES_DIS | \
+ DEFAULT_RX_TCP_QUEUE(0) | \
+ DEFAULT_RX_UDP_QUEUE(0) | \
+ DEFAULT_RX_BPDU_QUEUE(0)
+
+/* These macros describe Ethernet Port configuration extend reg (Px_cXR) bits*/
+#define CLASSIFY_EN (1 << 0)
+#define SPAN_BPDU_PACKETS_AS_NORMAL (0 << 1)
+#define SPAN_BPDU_PACKETS_TO_RX_QUEUE_7 (1 << 1)
+#define PARTITION_DISABLE (0 << 2)
+#define PARTITION_ENABLE (1 << 2)
+
+#define PORT_CONFIG_EXTEND_DEFAULT_VALUE \
+ SPAN_BPDU_PACKETS_AS_NORMAL | \
+ PARTITION_DISABLE
+
+/* These macros describe Ethernet Port Sdma configuration reg (SDCR) bits */
+#define RIFB (1 << 0)
+#define RX_BURST_SIZE_1_64BIT (0 << 1)
+#define RX_BURST_SIZE_2_64BIT (1 << 1)
+#define RX_BURST_SIZE_4_64BIT (2 << 1)
+#define RX_BURST_SIZE_8_64BIT (3 << 1)
+#define RX_BURST_SIZE_16_64BIT (4 << 1)
+#define BLM_RX_NO_SWAP (1 << 4)
+#define BLM_RX_BYTE_SWAP (0 << 4)
+#define BLM_TX_NO_SWAP (1 << 5)
+#define BLM_TX_BYTE_SWAP (0 << 5)
+#define DESCRIPTORS_BYTE_SWAP (1 << 6)
+#define DESCRIPTORS_NO_SWAP (0 << 6)
+#define IPG_INT_RX(value) (((value) & 0x3fff) << 8)
+#define TX_BURST_SIZE_1_64BIT (0 << 22)
+#define TX_BURST_SIZE_2_64BIT (1 << 22)
+#define TX_BURST_SIZE_4_64BIT (2 << 22)
+#define TX_BURST_SIZE_8_64BIT (3 << 22)
+#define TX_BURST_SIZE_16_64BIT (4 << 22)
+
+#if defined(__BIG_ENDIAN)
+#define PORT_SDMA_CONFIG_DEFAULT_VALUE \
+ RX_BURST_SIZE_4_64BIT | \
+ IPG_INT_RX(0) | \
+ TX_BURST_SIZE_4_64BIT
+#elif defined(__LITTLE_ENDIAN)
+#define PORT_SDMA_CONFIG_DEFAULT_VALUE \
+ RX_BURST_SIZE_4_64BIT | \
+ BLM_RX_NO_SWAP | \
+ BLM_TX_NO_SWAP | \
+ IPG_INT_RX(0) | \
+ TX_BURST_SIZE_4_64BIT
+#else
+#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
+#endif
+
+/* These macros describe Ethernet Port serial control reg (PSCR) bits */
+#define SERIAL_PORT_DISABLE (0 << 0)
+#define SERIAL_PORT_ENABLE (1 << 0)
+#define DO_NOT_FORCE_LINK_PASS (0 << 1)
+#define FORCE_LINK_PASS (1 << 1)
+#define ENABLE_AUTO_NEG_FOR_DUPLX (0 << 2)
+#define DISABLE_AUTO_NEG_FOR_DUPLX (1 << 2)
+#define ENABLE_AUTO_NEG_FOR_FLOW_CTRL (0 << 3)
+#define DISABLE_AUTO_NEG_FOR_FLOW_CTRL (1 << 3)
+#define ADV_NO_FLOW_CTRL (0 << 4)
+#define ADV_SYMMETRIC_FLOW_CTRL (1 << 4)
+#define FORCE_FC_MODE_NO_PAUSE_DIS_TX (0 << 5)
+#define FORCE_FC_MODE_TX_PAUSE_DIS (1 << 5)
+#define FORCE_BP_MODE_NO_JAM (0 << 7)
+#define FORCE_BP_MODE_JAM_TX (1 << 7)
+#define FORCE_BP_MODE_JAM_TX_ON_RX_ERR (2 << 7)
+#define SERIAL_PORT_CONTROL_RESERVED (1 << 9)
+#define FORCE_LINK_FAIL (0 << 10)
+#define DO_NOT_FORCE_LINK_FAIL (1 << 10)
+#define RETRANSMIT_16_ATTEMPTS (0 << 11)
+#define RETRANSMIT_FOREVER (1 << 11)
+#define ENABLE_AUTO_NEG_SPEED_GMII (0 << 13)
+#define DISABLE_AUTO_NEG_SPEED_GMII (1 << 13)
+#define DTE_ADV_0 (0 << 14)
+#define DTE_ADV_1 (1 << 14)
+#define DISABLE_AUTO_NEG_BYPASS (0 << 15)
+#define ENABLE_AUTO_NEG_BYPASS (1 << 15)
+#define AUTO_NEG_NO_CHANGE (0 << 16)
+#define RESTART_AUTO_NEG (1 << 16)
+#define MAX_RX_PACKET_1518BYTE (0 << 17)
+#define MAX_RX_PACKET_1522BYTE (1 << 17)
+#define MAX_RX_PACKET_1552BYTE (2 << 17)
+#define MAX_RX_PACKET_9022BYTE (3 << 17)
+#define MAX_RX_PACKET_9192BYTE (4 << 17)
+#define MAX_RX_PACKET_9700BYTE (5 << 17)
+#define MAX_RX_PACKET_MASK (7 << 17)
+#define CLR_EXT_LOOPBACK (0 << 20)
+#define SET_EXT_LOOPBACK (1 << 20)
+#define SET_HALF_DUPLEX_MODE (0 << 21)
+#define SET_FULL_DUPLEX_MODE (1 << 21)
+#define DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX (0 << 22)
+#define ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX (1 << 22)
+#define SET_GMII_SPEED_TO_10_100 (0 << 23)
+#define SET_GMII_SPEED_TO_1000 (1 << 23)
+#define SET_MII_SPEED_TO_10 (0 << 24)
+#define SET_MII_SPEED_TO_100 (1 << 24)
+
+#define PORT_SERIAL_CONTROL_DEFAULT_VALUE \
+ DO_NOT_FORCE_LINK_PASS | \
+ ENABLE_AUTO_NEG_FOR_DUPLX | \
+ DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
+ ADV_SYMMETRIC_FLOW_CTRL | \
+ FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
+ FORCE_BP_MODE_NO_JAM | \
+ (1 << 9) /* reserved */ | \
+ DO_NOT_FORCE_LINK_FAIL | \
+ RETRANSMIT_16_ATTEMPTS | \
+ ENABLE_AUTO_NEG_SPEED_GMII | \
+ DTE_ADV_0 | \
+ DISABLE_AUTO_NEG_BYPASS | \
+ AUTO_NEG_NO_CHANGE | \
+ MAX_RX_PACKET_9700BYTE | \
+ CLR_EXT_LOOPBACK | \
+ SET_FULL_DUPLEX_MODE | \
+ ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+/* These macros describe Ethernet Serial Status reg (PSR) bits */
+#define PORT_STATUS_MODE_10_BIT (1 << 0)
+#define PORT_STATUS_LINK_UP (1 << 1)
+#define PORT_STATUS_FULL_DUPLEX (1 << 2)
+#define PORT_STATUS_FLOW_CONTROL (1 << 3)
+#define PORT_STATUS_GMII_1000 (1 << 4)
+#define PORT_STATUS_MII_100 (1 << 5)
+/* PSR bit 6 is undocumented */
+#define PORT_STATUS_TX_IN_PROGRESS (1 << 7)
+#define PORT_STATUS_AUTONEG_BYPASSED (1 << 8)
+#define PORT_STATUS_PARTITION (1 << 9)
+#define PORT_STATUS_TX_FIFO_EMPTY (1 << 10)
+/* PSR bits 11-31 are reserved */
+
+#define PORT_DEFAULT_TRANSMIT_QUEUE_SIZE 800
+#define PORT_DEFAULT_RECEIVE_QUEUE_SIZE 400
+
+#define DESC_SIZE 64
+
+#define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */
+#define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */
+
+#define ETH_INT_CAUSE_RX_DONE (ETH_RX_QUEUES_ENABLED << 2)
+#define ETH_INT_CAUSE_RX_ERROR (ETH_RX_QUEUES_ENABLED << 9)
+#define ETH_INT_CAUSE_RX (ETH_INT_CAUSE_RX_DONE | ETH_INT_CAUSE_RX_ERROR)
+#define ETH_INT_CAUSE_EXT 0x00000002
+#define ETH_INT_UNMASK_ALL (ETH_INT_CAUSE_RX | ETH_INT_CAUSE_EXT)
+
+#define ETH_INT_CAUSE_TX_DONE (ETH_TX_QUEUES_ENABLED << 0)
+#define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8)
+#define ETH_INT_CAUSE_TX (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR)
+#define ETH_INT_CAUSE_PHY 0x00010000
+#define ETH_INT_CAUSE_STATE 0x00100000
+#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY | \
+ ETH_INT_CAUSE_STATE)
+
+#define ETH_INT_MASK_ALL 0x00000000
+#define ETH_INT_MASK_ALL_EXT 0x00000000
+
+#define PHY_WAIT_ITERATIONS 1000 /* 1000 iterations * 10uS = 10mS max */
+#define PHY_WAIT_MICRO_SECONDS 10
+
+/* Buffer offset from buffer pointer */
+#define RX_BUF_OFFSET 0x2
+
+/* Gigabit Ethernet Unit Global Registers */
+
+/* MIB Counters register definitions */
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4
+#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8
+#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc
+#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10
+#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c
+#define ETH_MIB_FRAMES_64_OCTETS 0x20
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34
+#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38
+#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c
+#define ETH_MIB_GOOD_FRAMES_SENT 0x40
+#define ETH_MIB_EXCESSIVE_COLLISION 0x44
+#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48
+#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c
+#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
+#define ETH_MIB_FC_SENT 0x54
+#define ETH_MIB_GOOD_FC_RECEIVED 0x58
+#define ETH_MIB_BAD_FC_RECEIVED 0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED 0x60
+#define ETH_MIB_FRAGMENTS_RECEIVED 0x64
+#define ETH_MIB_OVERSIZE_RECEIVED 0x68
+#define ETH_MIB_JABBER_RECEIVED 0x6c
+#define ETH_MIB_MAC_RECEIVE_ERROR 0x70
+#define ETH_MIB_BAD_CRC_EVENT 0x74
+#define ETH_MIB_COLLISION 0x78
+#define ETH_MIB_LATE_COLLISION 0x7c
+
+/* Port serial status reg (PSR) */
+#define ETH_INTERFACE_PCM 0x00000001
+#define ETH_LINK_IS_UP 0x00000002
+#define ETH_PORT_AT_FULL_DUPLEX 0x00000004
+#define ETH_RX_FLOW_CTRL_ENABLED 0x00000008
+#define ETH_GMII_SPEED_1000 0x00000010
+#define ETH_MII_SPEED_100 0x00000020
+#define ETH_TX_IN_PROGRESS 0x00000080
+#define ETH_BYPASS_ACTIVE 0x00000100
+#define ETH_PORT_AT_PARTITION_STATE 0x00000200
+#define ETH_PORT_TX_FIFO_EMPTY 0x00000400
+
+/* SMI reg */
+#define ETH_SMI_BUSY 0x10000000 /* 0 - Write, 1 - Read */
+#define ETH_SMI_READ_VALID 0x08000000 /* 0 - Write, 1 - Read */
+#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read */
+#define ETH_SMI_OPCODE_READ 0x04000000 /* Operation is in progress */
+
+/* Interrupt Cause Register Bit Definitions */
+
+/* SDMA command status fields macros */
+
+/* Tx & Rx descriptors status */
+#define ETH_ERROR_SUMMARY 0x00000001
+
+/* Tx & Rx descriptors command */
+#define ETH_BUFFER_OWNED_BY_DMA 0x80000000
+
+/* Tx descriptors status */
+#define ETH_LC_ERROR 0
+#define ETH_UR_ERROR 0x00000002
+#define ETH_RL_ERROR 0x00000004
+#define ETH_LLC_SNAP_FORMAT 0x00000200
+
+/* Rx descriptors status */
+#define ETH_OVERRUN_ERROR 0x00000002
+#define ETH_MAX_FRAME_LENGTH_ERROR 0x00000004
+#define ETH_RESOURCE_ERROR 0x00000006
+#define ETH_VLAN_TAGGED 0x00080000
+#define ETH_BPDU_FRAME 0x00100000
+#define ETH_UDP_FRAME_OVER_IP_V_4 0x00200000
+#define ETH_OTHER_FRAME_TYPE 0x00400000
+#define ETH_LAYER_2_IS_ETH_V_2 0x00800000
+#define ETH_FRAME_TYPE_IP_V_4 0x01000000
+#define ETH_FRAME_HEADER_OK 0x02000000
+#define ETH_RX_LAST_DESC 0x04000000
+#define ETH_RX_FIRST_DESC 0x08000000
+#define ETH_UNKNOWN_DESTINATION_ADDR 0x10000000
+#define ETH_RX_ENABLE_INTERRUPT 0x20000000
+#define ETH_LAYER_4_CHECKSUM_OK 0x40000000
+
+/* Rx descriptors byte count */
+#define ETH_FRAME_FRAGMENTED 0x00000004
+
+/* Tx descriptors command */
+#define ETH_LAYER_4_CHECKSUM_FIRST_DESC 0x00000400
+#define ETH_FRAME_SET_TO_VLAN 0x00008000
+#define ETH_UDP_FRAME 0x00010000
+#define ETH_GEN_TCP_UDP_CHECKSUM 0x00020000
+#define ETH_GEN_IP_V_4_CHECKSUM 0x00040000
+#define ETH_ZERO_PADDING 0x00080000
+#define ETH_TX_LAST_DESC 0x00100000
+#define ETH_TX_FIRST_DESC 0x00200000
+#define ETH_GEN_CRC 0x00400000
+#define ETH_TX_ENABLE_INTERRUPT 0x00800000
+#define ETH_AUTO_MODE 0x40000000
+
+#define ETH_TX_IHL_SHIFT 11
+
+/* typedefs */
+
+typedef enum _eth_func_ret_status {
+ ETH_OK, /* Returned as expected. */
+ ETH_ERROR, /* Fundamental error. */
+ ETH_RETRY, /* Could not process request. Try later.*/
+ ETH_END_OF_JOB, /* Ring has nothing to process. */
+ ETH_QUEUE_FULL, /* Ring resource error. */
+ ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */
+} ETH_FUNC_RET_STATUS;
+
+typedef enum _eth_target {
+ ETH_TARGET_DRAM,
+ ETH_TARGET_DEVICE,
+ ETH_TARGET_CBS,
+ ETH_TARGET_PCI0,
+ ETH_TARGET_PCI1
+} ETH_TARGET;
+
+/* These are for big-endian machines. Little endian needs different
+ * definitions.
+ */
+#if defined(__BIG_ENDIAN)
+struct eth_rx_desc {
+ u16 byte_cnt; /* Descriptor buffer byte count */
+ u16 buf_size; /* Buffer size */
+ u32 cmd_sts; /* Descriptor command status */
+ u32 next_desc_ptr; /* Next descriptor pointer */
+ u32 buf_ptr; /* Descriptor buffer pointer */
+};
+
+struct eth_tx_desc {
+ u16 byte_cnt; /* buffer byte count */
+ u16 l4i_chk; /* CPU provided TCP checksum */
+ u32 cmd_sts; /* Command/status field */
+ u32 next_desc_ptr; /* Pointer to next descriptor */
+ u32 buf_ptr; /* pointer to buffer for this descriptor*/
+};
+#elif defined(__LITTLE_ENDIAN)
+struct eth_rx_desc {
+ u32 cmd_sts; /* Descriptor command status */
+ u16 buf_size; /* Buffer size */
+ u16 byte_cnt; /* Descriptor buffer byte count */
+ u32 buf_ptr; /* Descriptor buffer pointer */
+ u32 next_desc_ptr; /* Next descriptor pointer */
+};
+
+struct eth_tx_desc {
+ u32 cmd_sts; /* Command/status field */
+ u16 l4i_chk; /* CPU provided TCP checksum */
+ u16 byte_cnt; /* buffer byte count */
+ u32 buf_ptr; /* pointer to buffer for this descriptor*/
+ u32 next_desc_ptr; /* Pointer to next descriptor */
+};
+#else
+#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
+#endif
+
+/* Unified struct for Rx and Tx operations. The user is not required to */
+/* be familier with neither Tx nor Rx descriptors. */
+struct pkt_info {
+ unsigned short byte_cnt; /* Descriptor buffer byte count */
+ unsigned short l4i_chk; /* Tx CPU provided TCP Checksum */
+ unsigned int cmd_sts; /* Descriptor command status */
+ dma_addr_t buf_ptr; /* Descriptor buffer pointer */
+ struct sk_buff *return_info; /* User resource return information */
+};
+
+/* Ethernet port specific information */
+struct mv643xx_mib_counters {
+ u64 good_octets_received;
+ u32 bad_octets_received;
+ u32 internal_mac_transmit_err;
+ u32 good_frames_received;
+ u32 bad_frames_received;
+ u32 broadcast_frames_received;
+ u32 multicast_frames_received;
+ u32 frames_64_octets;
+ u32 frames_65_to_127_octets;
+ u32 frames_128_to_255_octets;
+ u32 frames_256_to_511_octets;
+ u32 frames_512_to_1023_octets;
+ u32 frames_1024_to_max_octets;
+ u64 good_octets_sent;
+ u32 good_frames_sent;
+ u32 excessive_collision;
+ u32 multicast_frames_sent;
+ u32 broadcast_frames_sent;
+ u32 unrec_mac_control_received;
+ u32 fc_sent;
+ u32 good_fc_received;
+ u32 bad_fc_received;
+ u32 undersize_received;
+ u32 fragments_received;
+ u32 oversize_received;
+ u32 jabber_received;
+ u32 mac_receive_error;
+ u32 bad_crc_event;
+ u32 collision;
+ u32 late_collision;
+};
+
+struct mv643xx_private {
+ int port_num; /* User Ethernet port number */
+
+ u32 rx_sram_addr; /* Base address of rx sram area */
+ u32 rx_sram_size; /* Size of rx sram area */
+ u32 tx_sram_addr; /* Base address of tx sram area */
+ u32 tx_sram_size; /* Size of tx sram area */
+
+ int rx_resource_err; /* Rx ring resource error flag */
+
+ /* Tx/Rx rings managment indexes fields. For driver use */
+
+ /* Next available and first returning Rx resource */
+ int rx_curr_desc_q, rx_used_desc_q;
+
+ /* Next available and first returning Tx resource */
+ int tx_curr_desc_q, tx_used_desc_q;
+
+#ifdef MV643XX_TX_FAST_REFILL
+ u32 tx_clean_threshold;
+#endif
+
+ struct eth_rx_desc *p_rx_desc_area;
+ dma_addr_t rx_desc_dma;
+ int rx_desc_area_size;
+ struct sk_buff **rx_skb;
+
+ struct eth_tx_desc *p_tx_desc_area;
+ dma_addr_t tx_desc_dma;
+ int tx_desc_area_size;
+ struct sk_buff **tx_skb;
+
+ struct work_struct tx_timeout_task;
+
+ struct net_device *dev;
+ struct napi_struct napi;
+ struct net_device_stats stats;
+ struct mv643xx_mib_counters mib_counters;
+ spinlock_t lock;
+ /* Size of Tx Ring per queue */
+ int tx_ring_size;
+ /* Number of tx descriptors in use */
+ int tx_desc_count;
+ /* Size of Rx Ring per queue */
+ int rx_ring_size;
+ /* Number of rx descriptors in use */
+ int rx_desc_count;
+
+ /*
+ * Used in case RX Ring is empty, which can be caused when
+ * system does not have resources (skb's)
+ */
+ struct timer_list timeout;
+
+ u32 rx_int_coal;
+ u32 tx_int_coal;
+ struct mii_if_info mii;
+};
/* Static function declarations */
+static void eth_port_init(struct mv643xx_private *mp);
+static void eth_port_reset(unsigned int eth_port_num);
+static void eth_port_start(struct net_device *dev);
+
+static void ethernet_phy_reset(unsigned int eth_port_num);
+
+static void eth_port_write_smi_reg(unsigned int eth_port_num,
+ unsigned int phy_reg, unsigned int value);
+
+static void eth_port_read_smi_reg(unsigned int eth_port_num,
+ unsigned int phy_reg, unsigned int *value);
+
+static void eth_clear_mib_counters(unsigned int eth_port_num);
+
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+
static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr);
static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr);
static void eth_port_set_multicast_list(struct net_device *);
@@ -78,26 +631,19 @@ static const struct ethtool_ops mv643xx_ethtool_ops;
static char mv643xx_driver_name[] = "mv643xx_eth";
static char mv643xx_driver_version[] = "1.0";
-static void __iomem *mv643xx_eth_shared_base;
+static void __iomem *mv643xx_eth_base;
-/* used to protect MV643XX_ETH_SMI_REG, which is shared across ports */
+/* used to protect SMI_REG, which is shared across ports */
static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
static inline u32 mv_read(int offset)
{
- void __iomem *reg_base;
-
- reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
-
- return readl(reg_base + offset);
+ return readl(mv643xx_eth_base + offset);
}
static inline void mv_write(int offset, u32 data)
{
- void __iomem *reg_base;
-
- reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
- writel(data, reg_base + offset);
+ writel(data, mv643xx_eth_base + offset);
}
/*
@@ -221,12 +767,12 @@ static void mv643xx_eth_set_rx_mode(struct net_device *dev)
struct mv643xx_private *mp = netdev_priv(dev);
u32 config_reg;
- config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num));
+ config_reg = mv_read(PORT_CONFIG_REG(mp->port_num));
if (dev->flags & IFF_PROMISC)
- config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+ config_reg |= (u32) UNICAST_PROMISCUOUS_MODE;
else
- config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
- mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), config_reg);
+ config_reg &= ~(u32) UNICAST_PROMISCUOUS_MODE;
+ mv_write(PORT_CONFIG_REG(mp->port_num), config_reg);
eth_port_set_multicast_list(dev);
}
@@ -462,41 +1008,37 @@ static void mv643xx_eth_update_pscr(struct net_device *dev,
u32 o_pscr, n_pscr;
unsigned int queues;
- o_pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+ o_pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
n_pscr = o_pscr;
/* clear speed, duplex and rx buffer size fields */
- n_pscr &= ~(MV643XX_ETH_SET_MII_SPEED_TO_100 |
- MV643XX_ETH_SET_GMII_SPEED_TO_1000 |
- MV643XX_ETH_SET_FULL_DUPLEX_MODE |
- MV643XX_ETH_MAX_RX_PACKET_MASK);
+ n_pscr &= ~(SET_MII_SPEED_TO_100 |
+ SET_GMII_SPEED_TO_1000 |
+ SET_FULL_DUPLEX_MODE |
+ MAX_RX_PACKET_MASK);
if (ecmd->duplex == DUPLEX_FULL)
- n_pscr |= MV643XX_ETH_SET_FULL_DUPLEX_MODE;
+ n_pscr |= SET_FULL_DUPLEX_MODE;
if (ecmd->speed == SPEED_1000)
- n_pscr |= MV643XX_ETH_SET_GMII_SPEED_TO_1000 |
- MV643XX_ETH_MAX_RX_PACKET_9700BYTE;
+ n_pscr |= SET_GMII_SPEED_TO_1000 |
+ MAX_RX_PACKET_9700BYTE;
else {
if (ecmd->speed == SPEED_100)
- n_pscr |= MV643XX_ETH_SET_MII_SPEED_TO_100;
- n_pscr |= MV643XX_ETH_MAX_RX_PACKET_1522BYTE;
+ n_pscr |= SET_MII_SPEED_TO_100;
+ n_pscr |= MAX_RX_PACKET_1522BYTE;
}
if (n_pscr != o_pscr) {
- if ((o_pscr & MV643XX_ETH_SERIAL_PORT_ENABLE) == 0)
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
- n_pscr);
+ if ((o_pscr & SERIAL_PORT_ENABLE) == 0)
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
else {
queues = mv643xx_eth_port_disable_tx(port_num);
- o_pscr &= ~MV643XX_ETH_SERIAL_PORT_ENABLE;
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
- o_pscr);
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
- n_pscr);
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
- n_pscr);
+ o_pscr &= ~SERIAL_PORT_ENABLE;
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), o_pscr);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), n_pscr);
if (queues)
mv643xx_eth_port_enable_tx(port_num, queues);
}
@@ -522,13 +1064,13 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
unsigned int port_num = mp->port_num;
/* Read interrupt cause registers */
- eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
+ eth_int_cause = mv_read(INTERRUPT_CAUSE_REG(port_num)) &
ETH_INT_UNMASK_ALL;
if (eth_int_cause & ETH_INT_CAUSE_EXT) {
eth_int_cause_ext = mv_read(
- MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
+ INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
ETH_INT_UNMASK_ALL_EXT;
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),
+ mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num),
~eth_int_cause_ext);
}
@@ -556,10 +1098,10 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id)
#ifdef MV643XX_NAPI
if (eth_int_cause & ETH_INT_CAUSE_RX) {
/* schedule the NAPI poll routine to maintain port */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- ETH_INT_MASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+
/* wait for previous write to complete */
- mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+ mv_read(INTERRUPT_MASK_REG(port_num));
netif_rx_schedule(dev, &mp->napi);
}
@@ -611,9 +1153,9 @@ static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
unsigned int coal = ((t_clk / 1000000) * delay) / 64;
/* Set RX Coalescing mechanism */
- mv_write(MV643XX_ETH_SDMA_CONFIG_REG(eth_port_num),
+ mv_write(SDMA_CONFIG_REG(eth_port_num),
((coal & 0x3fff) << 8) |
- (mv_read(MV643XX_ETH_SDMA_CONFIG_REG(eth_port_num))
+ (mv_read(SDMA_CONFIG_REG(eth_port_num))
& 0xffc000ff));
return coal;
@@ -649,8 +1191,7 @@ static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
unsigned int coal;
coal = ((t_clk / 1000000) * delay) / 64;
/* Set TX Coalescing mechanism */
- mv_write(MV643XX_ETH_TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num),
- coal << 4);
+ mv_write(TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num), coal << 4);
return coal;
}
@@ -786,10 +1327,10 @@ static int mv643xx_eth_open(struct net_device *dev)
int err;
/* Clear any pending ethernet port interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+ mv_write(INTERRUPT_CAUSE_REG(port_num), 0);
+ mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
/* wait for previous write to complete */
- mv_read (MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num));
+ mv_read (INTERRUPT_CAUSE_EXTEND_REG(port_num));
err = request_irq(dev->irq, mv643xx_eth_int_handler,
IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, dev);
@@ -896,11 +1437,10 @@ static int mv643xx_eth_open(struct net_device *dev)
eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
/* Unmask phy and link status changes interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- ETH_INT_UNMASK_ALL_EXT);
+ mv_write(INTERRUPT_EXTEND_MASK_REG(port_num), ETH_INT_UNMASK_ALL_EXT);
/* Unmask RX buffer and TX end interrupt */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
return 0;
@@ -980,9 +1520,9 @@ static int mv643xx_eth_stop(struct net_device *dev)
unsigned int port_num = mp->port_num;
/* Mask all interrupts on ethernet port */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
/* wait for previous write to complete */
- mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+ mv_read(INTERRUPT_MASK_REG(port_num));
#ifdef MV643XX_NAPI
napi_disable(&mp->napi);
@@ -1021,16 +1561,15 @@ static int mv643xx_poll(struct napi_struct *napi, int budget)
#endif
work_done = 0;
- if ((mv_read(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
+ if ((mv_read(RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
!= (u32) mp->rx_used_desc_q)
work_done = mv643xx_eth_receive_queue(dev, budget);
if (work_done < budget) {
netif_rx_complete(dev, napi);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- ETH_INT_UNMASK_ALL);
+ mv_write(INTERRUPT_CAUSE_REG(port_num), 0);
+ mv_write(INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
}
return work_done;
@@ -1233,13 +1772,13 @@ static void mv643xx_netpoll(struct net_device *netdev)
struct mv643xx_private *mp = netdev_priv(netdev);
int port_num = mp->port_num;
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_MASK_ALL);
/* wait for previous write to complete */
- mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+ mv_read(INTERRUPT_MASK_REG(port_num));
mv643xx_eth_int_handler(netdev->irq, netdev);
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
+ mv_write(INTERRUPT_MASK_REG(port_num), ETH_INT_UNMASK_ALL);
}
#endif
@@ -1357,8 +1896,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
/* set default config values */
eth_port_uc_addr_get(port_num, dev->dev_addr);
- mp->rx_ring_size = MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
- mp->tx_ring_size = MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
+ mp->rx_ring_size = PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
+ mp->tx_ring_size = PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
if (is_valid_ether_addr(pd->mac_addr))
memcpy(dev->dev_addr, pd->mac_addr, 6);
@@ -1470,9 +2009,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
if (res == NULL)
return -ENODEV;
- mv643xx_eth_shared_base = ioremap(res->start,
- MV643XX_ETH_SHARED_REGS_SIZE);
- if (mv643xx_eth_shared_base == NULL)
+ mv643xx_eth_base = ioremap(res->start, res->end - res->start + 1);
+ if (mv643xx_eth_base == NULL)
return -ENOMEM;
return 0;
@@ -1481,8 +2019,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
static int mv643xx_eth_shared_remove(struct platform_device *pdev)
{
- iounmap(mv643xx_eth_shared_base);
- mv643xx_eth_shared_base = NULL;
+ iounmap(mv643xx_eth_base);
+ mv643xx_eth_base = NULL;
return 0;
}
@@ -1494,8 +2032,8 @@ static void mv643xx_eth_shutdown(struct platform_device *pdev)
unsigned int port_num = mp->port_num;
/* Mask all interrupts on ethernet port */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
- mv_read (MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+ mv_write(INTERRUPT_MASK_REG(port_num), 0);
+ mv_read (INTERRUPT_MASK_REG(port_num));
eth_port_reset(port_num);
}
@@ -1762,49 +2300,49 @@ static void eth_port_start(struct net_device *dev)
/* Assignment of Tx CTRP of given queue */
tx_curr_desc = mp->tx_curr_desc_q;
- mv_write(MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ mv_write(TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
(u32)((struct eth_tx_desc *)mp->tx_desc_dma + tx_curr_desc));
/* Assignment of Rx CRDP of given queue */
rx_curr_desc = mp->rx_curr_desc_q;
- mv_write(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ mv_write(RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
(u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
/* Add the assigned Ethernet address to the port's address table */
eth_port_uc_addr_set(port_num, dev->dev_addr);
/* Assign port configuration and command. */
- mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num),
- MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE);
+ mv_write(PORT_CONFIG_REG(port_num),
+ PORT_CONFIG_DEFAULT_VALUE);
- mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num),
- MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE);
+ mv_write(PORT_CONFIG_EXTEND_REG(port_num),
+ PORT_CONFIG_EXTEND_DEFAULT_VALUE);
- pscr = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+ pscr = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
- pscr &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE | MV643XX_ETH_FORCE_LINK_PASS);
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+ pscr &= ~(SERIAL_PORT_ENABLE | FORCE_LINK_PASS);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
- pscr |= MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
- MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII |
- MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX |
- MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL |
- MV643XX_ETH_SERIAL_PORT_CONTROL_RESERVED;
+ pscr |= DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
+ DISABLE_AUTO_NEG_SPEED_GMII |
+ DISABLE_AUTO_NEG_FOR_DUPLX |
+ DO_NOT_FORCE_LINK_FAIL |
+ SERIAL_PORT_CONTROL_RESERVED;
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
- pscr |= MV643XX_ETH_SERIAL_PORT_ENABLE;
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), pscr);
+ pscr |= SERIAL_PORT_ENABLE;
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), pscr);
/* Assign port SDMA configuration */
- mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num),
- MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE);
+ mv_write(SDMA_CONFIG_REG(port_num),
+ PORT_SDMA_CONFIG_DEFAULT_VALUE);
/* Enable port Rx. */
mv643xx_eth_port_enable_rx(port_num, ETH_RX_QUEUES_ENABLED);
/* Disable port bandwidth limits by clearing MTU register */
- mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0);
+ mv_write(MAXIMUM_TRANSMIT_UNIT(port_num), 0);
/* save phy settings across reset */
mv643xx_get_settings(dev, &ethtool_cmd);
@@ -1825,11 +2363,11 @@ static void eth_port_uc_addr_set(unsigned int port_num, unsigned char *p_addr)
mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
(p_addr[3] << 0);
- mv_write(MV643XX_ETH_MAC_ADDR_LOW(port_num), mac_l);
- mv_write(MV643XX_ETH_MAC_ADDR_HIGH(port_num), mac_h);
+ mv_write(MAC_ADDR_LOW(port_num), mac_l);
+ mv_write(MAC_ADDR_HIGH(port_num), mac_h);
/* Accept frames with this address */
- table = MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE(port_num);
+ table = DA_FILTER_UNICAST_TABLE_BASE(port_num);
eth_port_set_filter_table_entry(table, p_addr[5] & 0x0f);
}
@@ -1841,8 +2379,8 @@ static void eth_port_uc_addr_get(unsigned int port_num, unsigned char *p_addr)
unsigned int mac_h;
unsigned int mac_l;
- mac_h = mv_read(MV643XX_ETH_MAC_ADDR_HIGH(port_num));
- mac_l = mv_read(MV643XX_ETH_MAC_ADDR_LOW(port_num));
+ mac_h = mv_read(MAC_ADDR_HIGH(port_num));
+ mac_l = mv_read(MAC_ADDR_LOW(port_num));
p_addr[0] = (mac_h >> 24) & 0xff;
p_addr[1] = (mac_h >> 16) & 0xff;
@@ -1902,7 +2440,7 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) &&
(p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) {
- table = MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ table = DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
(eth_port_num);
eth_port_set_filter_table_entry(table, p_addr[5]);
return;
@@ -1976,7 +2514,7 @@ static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
for (i = 0; i < 8; i++)
crc_result = crc_result | (crc[i] << i);
- table = MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
+ table = DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
eth_port_set_filter_table_entry(table, crc_result);
}
@@ -2006,7 +2544,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
* 3-1 Queue ETH_Q0=0
* 7-4 Reserved = 0;
*/
- mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
/* Set all entries in DA filter other multicast
* table (Ex_dFOMT)
@@ -2016,7 +2554,7 @@ static void eth_port_set_multicast_list(struct net_device *dev)
* 3-1 Queue ETH_Q0=0
* 7-4 Reserved = 0;
*/
- mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
}
return;
}
@@ -2026,11 +2564,11 @@ static void eth_port_set_multicast_list(struct net_device *dev)
*/
for (table_index = 0; table_index <= 0xFC; table_index += 4) {
/* Clear DA filter special multicast table (Ex_dFSMT) */
- mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
/* Clear DA filter other multicast table (Ex_dFOMT) */
- mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
}
@@ -2064,15 +2602,15 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
/* Clear DA filter unicast table (Ex_dFUT) */
for (table_index = 0; table_index <= 0xC; table_index += 4)
- mv_write(MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+ mv_write(DA_FILTER_UNICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
for (table_index = 0; table_index <= 0xFC; table_index += 4) {
/* Clear DA filter special multicast table (Ex_dFSMT) */
- mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ mv_write(DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
/* Clear DA filter other multicast table (Ex_dFOMT) */
- mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ mv_write(DA_FILTER_OTHER_MULTICAST_TABLE_BASE
(eth_port_num) + table_index, 0);
}
}
@@ -2101,12 +2639,12 @@ static void eth_clear_mib_counters(unsigned int eth_port_num)
/* Perform dummy reads from MIB counters */
for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION;
i += 4)
- mv_read(MV643XX_ETH_MIB_COUNTERS_BASE(eth_port_num) + i);
+ mv_read(MIB_COUNTERS_BASE(eth_port_num) + i);
}
static inline u32 read_mib(struct mv643xx_private *mp, int offset)
{
- return mv_read(MV643XX_ETH_MIB_COUNTERS_BASE(mp->port_num) + offset);
+ return mv_read(MIB_COUNTERS_BASE(mp->port_num) + offset);
}
static void eth_update_mib_counters(struct mv643xx_private *mp)
@@ -2191,7 +2729,7 @@ static int ethernet_phy_get(unsigned int eth_port_num)
{
unsigned int reg_data;
- reg_data = mv_read(MV643XX_ETH_PHY_ADDR_REG);
+ reg_data = mv_read(PHY_ADDR_REG);
return ((reg_data >> (5 * eth_port_num)) & 0x1f);
}
@@ -2218,10 +2756,10 @@ static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
u32 reg_data;
int addr_shift = 5 * eth_port_num;
- reg_data = mv_read(MV643XX_ETH_PHY_ADDR_REG);
+ reg_data = mv_read(PHY_ADDR_REG);
reg_data &= ~(0x1f << addr_shift);
reg_data |= (phy_addr & 0x1f) << addr_shift;
- mv_write(MV643XX_ETH_PHY_ADDR_REG, reg_data);
+ mv_write(PHY_ADDR_REG, reg_data);
}
/*
@@ -2259,13 +2797,13 @@ static void ethernet_phy_reset(unsigned int eth_port_num)
static void mv643xx_eth_port_enable_tx(unsigned int port_num,
unsigned int queues)
{
- mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), queues);
+ mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), queues);
}
static void mv643xx_eth_port_enable_rx(unsigned int port_num,
unsigned int queues)
{
- mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), queues);
+ mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), queues);
}
static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
@@ -2273,21 +2811,18 @@ static unsigned int mv643xx_eth_port_disable_tx(unsigned int port_num)
u32 queues;
/* Stop Tx port activity. Check port Tx activity. */
- queues = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
- & 0xFF;
+ queues = mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF;
if (queues) {
/* Issue stop command for active queues only */
- mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
- (queues << 8));
+ mv_write(TRANSMIT_QUEUE_COMMAND_REG(port_num), (queues << 8));
/* Wait for all Tx activity to terminate. */
/* Check port cause register that all Tx queues are stopped */
- while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
- & 0xFF)
+ while (mv_read(TRANSMIT_QUEUE_COMMAND_REG(port_num)) & 0xFF)
udelay(PHY_WAIT_MICRO_SECONDS);
/* Wait for Tx FIFO to empty */
- while (mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num)) &
+ while (mv_read(PORT_STATUS_REG(port_num)) &
ETH_PORT_TX_FIFO_EMPTY)
udelay(PHY_WAIT_MICRO_SECONDS);
}
@@ -2300,17 +2835,14 @@ static unsigned int mv643xx_eth_port_disable_rx(unsigned int port_num)
u32 queues;
/* Stop Rx port activity. Check port Rx activity. */
- queues = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
- & 0xFF;
+ queues = mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF;
if (queues) {
/* Issue stop command for active queues only */
- mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
- (queues << 8));
+ mv_write(RECEIVE_QUEUE_COMMAND_REG(port_num), (queues << 8));
/* Wait for all Rx activity to terminate. */
/* Check port cause register that all Rx queues are stopped */
- while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
- & 0xFF)
+ while (mv_read(RECEIVE_QUEUE_COMMAND_REG(port_num)) & 0xFF)
udelay(PHY_WAIT_MICRO_SECONDS);
}
@@ -2346,11 +2878,11 @@ static void eth_port_reset(unsigned int port_num)
eth_clear_mib_counters(port_num);
/* Reset the Enable bit in the Configuration Register */
- reg_data = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
- reg_data &= ~(MV643XX_ETH_SERIAL_PORT_ENABLE |
- MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL |
- MV643XX_ETH_FORCE_LINK_PASS);
- mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
+ reg_data = mv_read(PORT_SERIAL_CONTROL_REG(port_num));
+ reg_data &= ~(SERIAL_PORT_ENABLE |
+ DO_NOT_FORCE_LINK_FAIL |
+ FORCE_LINK_PASS);
+ mv_write(PORT_SERIAL_CONTROL_REG(port_num), reg_data);
}
@@ -2385,7 +2917,7 @@ static void eth_port_read_smi_reg(unsigned int port_num,
spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
/* wait for the SMI register to become available */
- for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
+ for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
if (i == PHY_WAIT_ITERATIONS) {
printk("mv643xx PHY busy timeout, port %d\n", port_num);
goto out;
@@ -2393,11 +2925,11 @@ static void eth_port_read_smi_reg(unsigned int port_num,
udelay(PHY_WAIT_MICRO_SECONDS);
}
- mv_write(MV643XX_ETH_SMI_REG,
+ mv_write(SMI_REG,
(phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
/* now wait for the data to be valid */
- for (i = 0; !(mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_READ_VALID); i++) {
+ for (i = 0; !(mv_read(SMI_REG) & ETH_SMI_READ_VALID); i++) {
if (i == PHY_WAIT_ITERATIONS) {
printk("mv643xx PHY read timeout, port %d\n", port_num);
goto out;
@@ -2405,7 +2937,7 @@ static void eth_port_read_smi_reg(unsigned int port_num,
udelay(PHY_WAIT_MICRO_SECONDS);
}
- *value = mv_read(MV643XX_ETH_SMI_REG) & 0xffff;
+ *value = mv_read(SMI_REG) & 0xffff;
out:
spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
}
@@ -2443,7 +2975,7 @@ static void eth_port_write_smi_reg(unsigned int eth_port_num,
spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
/* wait for the SMI register to become available */
- for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
+ for (i = 0; mv_read(SMI_REG) & ETH_SMI_BUSY; i++) {
if (i == PHY_WAIT_ITERATIONS) {
printk("mv643xx PHY busy timeout, port %d\n",
eth_port_num);
@@ -2452,7 +2984,7 @@ static void eth_port_write_smi_reg(unsigned int eth_port_num,
udelay(PHY_WAIT_MICRO_SECONDS);
}
- mv_write(MV643XX_ETH_SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
+ mv_write(SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
ETH_SMI_OPCODE_WRITE | (value & 0xffff));
out:
spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
@@ -2742,6 +3274,7 @@ static const struct ethtool_ops mv643xx_ethtool_ops = {
.get_drvinfo = mv643xx_get_drvinfo,
.get_link = mv643xx_eth_get_link,
.set_sg = ethtool_op_set_sg,
+ .get_sset_count = mv643xx_get_sset_count,
.get_ethtool_stats = mv643xx_get_ethtool_stats,
.get_strings = mv643xx_get_strings,
.nway_reset = mv643xx_eth_nway_restart,
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
deleted file mode 100644
index be669eb2378..00000000000
--- a/drivers/net/mv643xx_eth.h
+++ /dev/null
@@ -1,370 +0,0 @@
-#ifndef __MV643XX_ETH_H__
-#define __MV643XX_ETH_H__
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/mii.h>
-
-#include <linux/mv643xx.h>
-
-#include <asm/dma-mapping.h>
-
-/* Checksum offload for Tx works for most packets, but
- * fails if previous packet sent did not use hw csum
- */
-#define MV643XX_CHECKSUM_OFFLOAD_TX
-#define MV643XX_NAPI
-#define MV643XX_TX_FAST_REFILL
-#undef MV643XX_COAL
-
-/*
- * Number of RX / TX descriptors on RX / TX rings.
- * Note that allocating RX descriptors is done by allocating the RX
- * ring AND a preallocated RX buffers (skb's) for each descriptor.
- * The TX descriptors only allocates the TX descriptors ring,
- * with no pre allocated TX buffers (skb's are allocated by higher layers.
- */
-
-/* Default TX ring size is 1000 descriptors */
-#define MV643XX_DEFAULT_TX_QUEUE_SIZE 1000
-
-/* Default RX ring size is 400 descriptors */
-#define MV643XX_DEFAULT_RX_QUEUE_SIZE 400
-
-#define MV643XX_TX_COAL 100
-#ifdef MV643XX_COAL
-#define MV643XX_RX_COAL 100
-#endif
-
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
-#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
-#else
-#define MAX_DESCS_PER_SKB 1
-#endif
-
-#define ETH_VLAN_HLEN 4
-#define ETH_FCS_LEN 4
-#define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */
-#define ETH_WRAPPER_LEN (ETH_HW_IP_ALIGN + ETH_HLEN + \
- ETH_VLAN_HLEN + ETH_FCS_LEN)
-#define ETH_RX_SKB_SIZE (dev->mtu + ETH_WRAPPER_LEN + dma_get_cache_alignment())
-
-#define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */
-#define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */
-
-#define ETH_INT_CAUSE_RX_DONE (ETH_RX_QUEUES_ENABLED << 2)
-#define ETH_INT_CAUSE_RX_ERROR (ETH_RX_QUEUES_ENABLED << 9)
-#define ETH_INT_CAUSE_RX (ETH_INT_CAUSE_RX_DONE | ETH_INT_CAUSE_RX_ERROR)
-#define ETH_INT_CAUSE_EXT 0x00000002
-#define ETH_INT_UNMASK_ALL (ETH_INT_CAUSE_RX | ETH_INT_CAUSE_EXT)
-
-#define ETH_INT_CAUSE_TX_DONE (ETH_TX_QUEUES_ENABLED << 0)
-#define ETH_INT_CAUSE_TX_ERROR (ETH_TX_QUEUES_ENABLED << 8)
-#define ETH_INT_CAUSE_TX (ETH_INT_CAUSE_TX_DONE | ETH_INT_CAUSE_TX_ERROR)
-#define ETH_INT_CAUSE_PHY 0x00010000
-#define ETH_INT_CAUSE_STATE 0x00100000
-#define ETH_INT_UNMASK_ALL_EXT (ETH_INT_CAUSE_TX | ETH_INT_CAUSE_PHY | \
- ETH_INT_CAUSE_STATE)
-
-#define ETH_INT_MASK_ALL 0x00000000
-#define ETH_INT_MASK_ALL_EXT 0x00000000
-
-#define PHY_WAIT_ITERATIONS 1000 /* 1000 iterations * 10uS = 10mS max */
-#define PHY_WAIT_MICRO_SECONDS 10
-
-/* Buffer offset from buffer pointer */
-#define RX_BUF_OFFSET 0x2
-
-/* Gigabit Ethernet Unit Global Registers */
-
-/* MIB Counters register definitions */
-#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0
-#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4
-#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8
-#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc
-#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10
-#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14
-#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18
-#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c
-#define ETH_MIB_FRAMES_64_OCTETS 0x20
-#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24
-#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28
-#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c
-#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30
-#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34
-#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38
-#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c
-#define ETH_MIB_GOOD_FRAMES_SENT 0x40
-#define ETH_MIB_EXCESSIVE_COLLISION 0x44
-#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48
-#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c
-#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
-#define ETH_MIB_FC_SENT 0x54
-#define ETH_MIB_GOOD_FC_RECEIVED 0x58
-#define ETH_MIB_BAD_FC_RECEIVED 0x5c
-#define ETH_MIB_UNDERSIZE_RECEIVED 0x60
-#define ETH_MIB_FRAGMENTS_RECEIVED 0x64
-#define ETH_MIB_OVERSIZE_RECEIVED 0x68
-#define ETH_MIB_JABBER_RECEIVED 0x6c
-#define ETH_MIB_MAC_RECEIVE_ERROR 0x70
-#define ETH_MIB_BAD_CRC_EVENT 0x74
-#define ETH_MIB_COLLISION 0x78
-#define ETH_MIB_LATE_COLLISION 0x7c
-
-/* Port serial status reg (PSR) */
-#define ETH_INTERFACE_PCM 0x00000001
-#define ETH_LINK_IS_UP 0x00000002
-#define ETH_PORT_AT_FULL_DUPLEX 0x00000004
-#define ETH_RX_FLOW_CTRL_ENABLED 0x00000008
-#define ETH_GMII_SPEED_1000 0x00000010
-#define ETH_MII_SPEED_100 0x00000020
-#define ETH_TX_IN_PROGRESS 0x00000080
-#define ETH_BYPASS_ACTIVE 0x00000100
-#define ETH_PORT_AT_PARTITION_STATE 0x00000200
-#define ETH_PORT_TX_FIFO_EMPTY 0x00000400
-
-/* SMI reg */
-#define ETH_SMI_BUSY 0x10000000 /* 0 - Write, 1 - Read */
-#define ETH_SMI_READ_VALID 0x08000000 /* 0 - Write, 1 - Read */
-#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read */
-#define ETH_SMI_OPCODE_READ 0x04000000 /* Operation is in progress */
-
-/* Interrupt Cause Register Bit Definitions */
-
-/* SDMA command status fields macros */
-
-/* Tx & Rx descriptors status */
-#define ETH_ERROR_SUMMARY 0x00000001
-
-/* Tx & Rx descriptors command */
-#define ETH_BUFFER_OWNED_BY_DMA 0x80000000
-
-/* Tx descriptors status */
-#define ETH_LC_ERROR 0
-#define ETH_UR_ERROR 0x00000002
-#define ETH_RL_ERROR 0x00000004
-#define ETH_LLC_SNAP_FORMAT 0x00000200
-
-/* Rx descriptors status */
-#define ETH_OVERRUN_ERROR 0x00000002
-#define ETH_MAX_FRAME_LENGTH_ERROR 0x00000004
-#define ETH_RESOURCE_ERROR 0x00000006
-#define ETH_VLAN_TAGGED 0x00080000
-#define ETH_BPDU_FRAME 0x00100000
-#define ETH_UDP_FRAME_OVER_IP_V_4 0x00200000
-#define ETH_OTHER_FRAME_TYPE 0x00400000
-#define ETH_LAYER_2_IS_ETH_V_2 0x00800000
-#define ETH_FRAME_TYPE_IP_V_4 0x01000000
-#define ETH_FRAME_HEADER_OK 0x02000000
-#define ETH_RX_LAST_DESC 0x04000000
-#define ETH_RX_FIRST_DESC 0x08000000
-#define ETH_UNKNOWN_DESTINATION_ADDR 0x10000000
-#define ETH_RX_ENABLE_INTERRUPT 0x20000000
-#define ETH_LAYER_4_CHECKSUM_OK 0x40000000
-
-/* Rx descriptors byte count */
-#define ETH_FRAME_FRAGMENTED 0x00000004
-
-/* Tx descriptors command */
-#define ETH_LAYER_4_CHECKSUM_FIRST_DESC 0x00000400
-#define ETH_FRAME_SET_TO_VLAN 0x00008000
-#define ETH_UDP_FRAME 0x00010000
-#define ETH_GEN_TCP_UDP_CHECKSUM 0x00020000
-#define ETH_GEN_IP_V_4_CHECKSUM 0x00040000
-#define ETH_ZERO_PADDING 0x00080000
-#define ETH_TX_LAST_DESC 0x00100000
-#define ETH_TX_FIRST_DESC 0x00200000
-#define ETH_GEN_CRC 0x00400000
-#define ETH_TX_ENABLE_INTERRUPT 0x00800000
-#define ETH_AUTO_MODE 0x40000000
-
-#define ETH_TX_IHL_SHIFT 11
-
-/* typedefs */
-
-typedef enum _eth_func_ret_status {
- ETH_OK, /* Returned as expected. */
- ETH_ERROR, /* Fundamental error. */
- ETH_RETRY, /* Could not process request. Try later.*/
- ETH_END_OF_JOB, /* Ring has nothing to process. */
- ETH_QUEUE_FULL, /* Ring resource error. */
- ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */
-} ETH_FUNC_RET_STATUS;
-
-typedef enum _eth_target {
- ETH_TARGET_DRAM,
- ETH_TARGET_DEVICE,
- ETH_TARGET_CBS,
- ETH_TARGET_PCI0,
- ETH_TARGET_PCI1
-} ETH_TARGET;
-
-/* These are for big-endian machines. Little endian needs different
- * definitions.
- */
-#if defined(__BIG_ENDIAN)
-struct eth_rx_desc {
- u16 byte_cnt; /* Descriptor buffer byte count */
- u16 buf_size; /* Buffer size */
- u32 cmd_sts; /* Descriptor command status */
- u32 next_desc_ptr; /* Next descriptor pointer */
- u32 buf_ptr; /* Descriptor buffer pointer */
-};
-
-struct eth_tx_desc {
- u16 byte_cnt; /* buffer byte count */
- u16 l4i_chk; /* CPU provided TCP checksum */
- u32 cmd_sts; /* Command/status field */
- u32 next_desc_ptr; /* Pointer to next descriptor */
- u32 buf_ptr; /* pointer to buffer for this descriptor*/
-};
-
-#elif defined(__LITTLE_ENDIAN)
-struct eth_rx_desc {
- u32 cmd_sts; /* Descriptor command status */
- u16 buf_size; /* Buffer size */
- u16 byte_cnt; /* Descriptor buffer byte count */
- u32 buf_ptr; /* Descriptor buffer pointer */
- u32 next_desc_ptr; /* Next descriptor pointer */
-};
-
-struct eth_tx_desc {
- u32 cmd_sts; /* Command/status field */
- u16 l4i_chk; /* CPU provided TCP checksum */
- u16 byte_cnt; /* buffer byte count */
- u32 buf_ptr; /* pointer to buffer for this descriptor*/
- u32 next_desc_ptr; /* Pointer to next descriptor */
-};
-#else
-#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
-#endif
-
-/* Unified struct for Rx and Tx operations. The user is not required to */
-/* be familier with neither Tx nor Rx descriptors. */
-struct pkt_info {
- unsigned short byte_cnt; /* Descriptor buffer byte count */
- unsigned short l4i_chk; /* Tx CPU provided TCP Checksum */
- unsigned int cmd_sts; /* Descriptor command status */
- dma_addr_t buf_ptr; /* Descriptor buffer pointer */
- struct sk_buff *return_info; /* User resource return information */
-};
-
-/* Ethernet port specific information */
-
-struct mv643xx_mib_counters {
- u64 good_octets_received;
- u32 bad_octets_received;
- u32 internal_mac_transmit_err;
- u32 good_frames_received;
- u32 bad_frames_received;
- u32 broadcast_frames_received;
- u32 multicast_frames_received;
- u32 frames_64_octets;
- u32 frames_65_to_127_octets;
- u32 frames_128_to_255_octets;
- u32 frames_256_to_511_octets;
- u32 frames_512_to_1023_octets;
- u32 frames_1024_to_max_octets;
- u64 good_octets_sent;
- u32 good_frames_sent;
- u32 excessive_collision;
- u32 multicast_frames_sent;
- u32 broadcast_frames_sent;
- u32 unrec_mac_control_received;
- u32 fc_sent;
- u32 good_fc_received;
- u32 bad_fc_received;
- u32 undersize_received;
- u32 fragments_received;
- u32 oversize_received;
- u32 jabber_received;
- u32 mac_receive_error;
- u32 bad_crc_event;
- u32 collision;
- u32 late_collision;
-};
-
-struct mv643xx_private {
- int port_num; /* User Ethernet port number */
-
- u32 rx_sram_addr; /* Base address of rx sram area */
- u32 rx_sram_size; /* Size of rx sram area */
- u32 tx_sram_addr; /* Base address of tx sram area */
- u32 tx_sram_size; /* Size of tx sram area */
-
- int rx_resource_err; /* Rx ring resource error flag */
-
- /* Tx/Rx rings managment indexes fields. For driver use */
-
- /* Next available and first returning Rx resource */
- int rx_curr_desc_q, rx_used_desc_q;
-
- /* Next available and first returning Tx resource */
- int tx_curr_desc_q, tx_used_desc_q;
-
-#ifdef MV643XX_TX_FAST_REFILL
- u32 tx_clean_threshold;
-#endif
-
- struct eth_rx_desc *p_rx_desc_area;
- dma_addr_t rx_desc_dma;
- int rx_desc_area_size;
- struct sk_buff **rx_skb;
-
- struct eth_tx_desc *p_tx_desc_area;
- dma_addr_t tx_desc_dma;
- int tx_desc_area_size;
- struct sk_buff **tx_skb;
-
- struct work_struct tx_timeout_task;
-
- struct net_device *dev;
- struct napi_struct napi;
- struct net_device_stats stats;
- struct mv643xx_mib_counters mib_counters;
- spinlock_t lock;
- /* Size of Tx Ring per queue */
- int tx_ring_size;
- /* Number of tx descriptors in use */
- int tx_desc_count;
- /* Size of Rx Ring per queue */
- int rx_ring_size;
- /* Number of rx descriptors in use */
- int rx_desc_count;
-
- /*
- * Used in case RX Ring is empty, which can be caused when
- * system does not have resources (skb's)
- */
- struct timer_list timeout;
-
- u32 rx_int_coal;
- u32 tx_int_coal;
- struct mii_if_info mii;
-};
-
-/* Port operation control routines */
-static void eth_port_init(struct mv643xx_private *mp);
-static void eth_port_reset(unsigned int eth_port_num);
-static void eth_port_start(struct net_device *dev);
-
-/* PHY and MIB routines */
-static void ethernet_phy_reset(unsigned int eth_port_num);
-
-static void eth_port_write_smi_reg(unsigned int eth_port_num,
- unsigned int phy_reg, unsigned int value);
-
-static void eth_port_read_smi_reg(unsigned int eth_port_num,
- unsigned int phy_reg, unsigned int *value);
-
-static void eth_clear_mib_counters(unsigned int eth_port_num);
-
-/* Port data flow control routines */
-static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
- struct pkt_info *p_pkt_info);
-static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
- struct pkt_info *p_pkt_info);
-
-#endif /* __MV643XX_ETH_H__ */
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c
index 14a768fbce2..a20005c09e0 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ni5010.c
@@ -518,7 +518,6 @@ static void dump_packet(void *buf, int len)
/* We have a good packet, get it out of the buffer. */
static void ni5010_rx(struct net_device *dev)
{
- struct ni5010_local *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
unsigned char rcv_stat;
struct sk_buff *skb;
@@ -577,7 +576,6 @@ static void ni5010_rx(struct net_device *dev)
PRINTK2((KERN_DEBUG "%s: Received packet, size=%#4.4x\n",
dev->name, i_pkt_size));
-
}
static int process_xmt_interrupt(struct net_device *dev)
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 9f9a421c99b..ab4d309a858 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -550,7 +550,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
n = mac->rx->next_to_clean;
- prefetch(RX_RING(mac, n));
+ prefetch(&RX_RING(mac, n));
for (count = 0; count < limit; count++) {
macrx = RX_RING(mac, n);
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 419c00cbe6e..e8960f294a6 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -44,7 +44,8 @@
printk( "Assertion failed! %s,%s,%s,line=%d\n", \
#expr,__FILE__,__FUNCTION__,__LINE__); \
}
-#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0)
+#define dprintk(fmt, args...) \
+ do { printk(KERN_DEBUG PFX fmt, ## args); } while (0)
#else
#define assert(expr) do {} while (0)
#define dprintk(fmt, args...) do {} while (0)
@@ -111,19 +112,15 @@ enum mac_version {
RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
- RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be 8168Bf
- RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb 8101Ec
- RTL_GIGA_MAC_VER_14 = 0x0e, // 8101
- RTL_GIGA_MAC_VER_15 = 0x0f // 8101
-};
-
-enum phy_version {
- RTL_GIGA_PHY_VER_C = 0x03, /* PHY Reg 0x03 bit0-3 == 0x0000 */
- RTL_GIGA_PHY_VER_D = 0x04, /* PHY Reg 0x03 bit0-3 == 0x0000 */
- RTL_GIGA_PHY_VER_E = 0x05, /* PHY Reg 0x03 bit0-3 == 0x0000 */
- RTL_GIGA_PHY_VER_F = 0x06, /* PHY Reg 0x03 bit0-3 == 0x0001 */
- RTL_GIGA_PHY_VER_G = 0x07, /* PHY Reg 0x03 bit0-3 == 0x0002 */
- RTL_GIGA_PHY_VER_H = 0x08, /* PHY Reg 0x03 bit0-3 == 0x0003 */
+ RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be
+ RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb
+ RTL_GIGA_MAC_VER_14 = 0x0e, // 8101 ?
+ RTL_GIGA_MAC_VER_15 = 0x0f, // 8101 ?
+ RTL_GIGA_MAC_VER_16 = 0x11, // 8101Ec
+ RTL_GIGA_MAC_VER_17 = 0x10, // 8168Bf
+ RTL_GIGA_MAC_VER_18 = 0x12, // 8168CP
+ RTL_GIGA_MAC_VER_19 = 0x13, // 8168C
+ RTL_GIGA_MAC_VER_20 = 0x14 // 8168C
};
#define _R(NAME,MAC,MASK) \
@@ -144,7 +141,12 @@ static const struct {
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
_R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
_R("RTL8100e", RTL_GIGA_MAC_VER_14, 0xff7e1880), // PCI-E 8139
- _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880) // PCI-E 8139
+ _R("RTL8100e", RTL_GIGA_MAC_VER_15, 0xff7e1880), // PCI-E 8139
+ _R("RTL8168b/8111b", RTL_GIGA_MAC_VER_17, 0xff7e1880), // PCI-E
+ _R("RTL8101e", RTL_GIGA_MAC_VER_16, 0xff7e1880), // PCI-E
+ _R("RTL8168cp/8111cp", RTL_GIGA_MAC_VER_18, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_19, 0xff7e1880), // PCI-E
+ _R("RTL8168c/8111c", RTL_GIGA_MAC_VER_20, 0xff7e1880) // PCI-E
};
#undef _R
@@ -165,7 +167,7 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
- { PCI_DEVICE(0x1259, 0xc107), 0, 0, RTL_CFG_0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
{ PCI_VENDOR_ID_LINKSYS, 0x1032,
PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
@@ -277,6 +279,7 @@ enum rtl_register_content {
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
/* Config1 register p.24 */
+ MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */
PMEnable = (1 << 0), /* Power Management Enable */
/* Config2 register p. 25 */
@@ -380,17 +383,20 @@ struct ring_info {
u8 __pad[sizeof(void *) - sizeof(u32)];
};
+enum features {
+ RTL_FEATURE_WOL = (1 << 0),
+ RTL_FEATURE_MSI = (1 << 1),
+};
+
struct rtl8169_private {
void __iomem *mmio_addr; /* memory map physical address */
struct pci_dev *pci_dev; /* Index of PCI device */
struct net_device *dev;
struct napi_struct napi;
- struct net_device_stats stats; /* statistics of net device */
spinlock_t lock; /* spin lock flag */
u32 msg_enable;
int chipset;
int mac_version;
- int phy_version;
u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
u32 dirty_rx;
@@ -420,7 +426,7 @@ struct rtl8169_private {
unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *);
struct delayed_work task;
- unsigned wol_enabled : 1;
+ unsigned features;
};
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -626,7 +632,10 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
RTL_W8(Cfg9346, Cfg9346_Lock);
- tp->wol_enabled = (wol->wolopts) ? 1 : 0;
+ if (wol->wolopts)
+ tp->features |= RTL_FEATURE_WOL;
+ else
+ tp->features &= ~RTL_FEATURE_WOL;
spin_unlock_irq(&tp->lock);
@@ -707,7 +716,8 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
/* This tweak comes straight from Realtek's driver. */
if ((speed == SPEED_100) && (duplex == DUPLEX_HALF) &&
- (tp->mac_version == RTL_GIGA_MAC_VER_13)) {
+ ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16))) {
auto_nego = ADVERTISE_100HALF | ADVERTISE_CSMA;
}
}
@@ -715,7 +725,8 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
/* The 8100e/8101e do Fast Ethernet only. */
if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
(tp->mac_version == RTL_GIGA_MAC_VER_14) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_15)) {
+ (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16)) {
if ((giga_ctrl & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
netif_msg_link(tp)) {
printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n",
@@ -726,7 +737,8 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
- if (tp->mac_version == RTL_GIGA_MAC_VER_12) {
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_12) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_17)) {
/* Vendor specific (0x1f) and reserved (0x0e) MII registers. */
mdio_write(ioaddr, 0x1f, 0x0000);
mdio_write(ioaddr, 0x0e, 0x0000);
@@ -1104,26 +1116,51 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
*/
const struct {
u32 mask;
+ u32 val;
int mac_version;
} mac_info[] = {
- { 0x38800000, RTL_GIGA_MAC_VER_15 },
- { 0x38000000, RTL_GIGA_MAC_VER_12 },
- { 0x34000000, RTL_GIGA_MAC_VER_13 },
- { 0x30800000, RTL_GIGA_MAC_VER_14 },
- { 0x30000000, RTL_GIGA_MAC_VER_11 },
- { 0x98000000, RTL_GIGA_MAC_VER_06 },
- { 0x18000000, RTL_GIGA_MAC_VER_05 },
- { 0x10000000, RTL_GIGA_MAC_VER_04 },
- { 0x04000000, RTL_GIGA_MAC_VER_03 },
- { 0x00800000, RTL_GIGA_MAC_VER_02 },
- { 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */
+ /* 8168B family. */
+ { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
+ { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
+ { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
+ { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_20 },
+
+ /* 8168B family. */
+ { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
+ { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
+ { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
+ { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
+
+ /* 8101 family. */
+ { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
+ { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
+ { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
+ /* FIXME: where did these entries come from ? -- FR */
+ { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
+ { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
+
+ /* 8110 family. */
+ { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
+ { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
+ { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
+ { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
+ { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
+ { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
+
+ { 0x00000000, 0x00000000, RTL_GIGA_MAC_VER_01 } /* Catch-all */
}, *p = mac_info;
u32 reg;
- reg = RTL_R32(TxConfig) & 0xfc800000;
- while ((reg & p->mask) != p->mask)
+ reg = RTL_R32(TxConfig);
+ while ((reg & p->mask) != p->val)
p++;
tp->mac_version = p->mac_version;
+
+ if (p->mask == 0x00000000) {
+ struct pci_dev *pdev = tp->pci_dev;
+
+ dev_info(&pdev->dev, "unknown MAC (%08x)\n", reg);
+ }
}
static void rtl8169_print_mac_version(struct rtl8169_private *tp)
@@ -1131,54 +1168,21 @@ static void rtl8169_print_mac_version(struct rtl8169_private *tp)
dprintk("mac_version = 0x%02x\n", tp->mac_version);
}
-static void rtl8169_get_phy_version(struct rtl8169_private *tp,
- void __iomem *ioaddr)
-{
- const struct {
- u16 mask;
- u16 set;
- int phy_version;
- } phy_info[] = {
- { 0x000f, 0x0002, RTL_GIGA_PHY_VER_G },
- { 0x000f, 0x0001, RTL_GIGA_PHY_VER_F },
- { 0x000f, 0x0000, RTL_GIGA_PHY_VER_E },
- { 0x0000, 0x0000, RTL_GIGA_PHY_VER_D } /* Catch-all */
- }, *p = phy_info;
+struct phy_reg {
u16 reg;
+ u16 val;
+};
- reg = mdio_read(ioaddr, MII_PHYSID2) & 0xffff;
- while ((reg & p->mask) != p->set)
- p++;
- tp->phy_version = p->phy_version;
-}
-
-static void rtl8169_print_phy_version(struct rtl8169_private *tp)
+static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len)
{
- struct {
- int version;
- char *msg;
- u32 reg;
- } phy_print[] = {
- { RTL_GIGA_PHY_VER_G, "RTL_GIGA_PHY_VER_G", 0x0002 },
- { RTL_GIGA_PHY_VER_F, "RTL_GIGA_PHY_VER_F", 0x0001 },
- { RTL_GIGA_PHY_VER_E, "RTL_GIGA_PHY_VER_E", 0x0000 },
- { RTL_GIGA_PHY_VER_D, "RTL_GIGA_PHY_VER_D", 0x0000 },
- { 0, NULL, 0x0000 }
- }, *p;
-
- for (p = phy_print; p->msg; p++) {
- if (tp->phy_version == p->version) {
- dprintk("phy_version == %s (%04x)\n", p->msg, p->reg);
- return;
- }
+ while (len-- > 0) {
+ mdio_write(ioaddr, regs->reg, regs->val);
+ regs++;
}
- dprintk("phy_version == Unknown\n");
}
-static void rtl8169_hw_phy_config(struct net_device *dev)
+static void rtl8169s_hw_phy_config(void __iomem *ioaddr)
{
- struct rtl8169_private *tp = netdev_priv(dev);
- void __iomem *ioaddr = tp->mmio_addr;
struct {
u16 regs[5]; /* Beware of bit-sign propagation */
} phy_magic[5] = { {
@@ -1211,33 +1215,9 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
}, *p = phy_magic;
unsigned int i;
- rtl8169_print_mac_version(tp);
- rtl8169_print_phy_version(tp);
-
- if (tp->mac_version <= RTL_GIGA_MAC_VER_01)
- return;
- if (tp->phy_version >= RTL_GIGA_PHY_VER_H)
- return;
-
- dprintk("MAC version != 0 && PHY version == 0 or 1\n");
- dprintk("Do final_reg2.cfg\n");
-
- /* Shazam ! */
-
- if (tp->mac_version == RTL_GIGA_MAC_VER_04) {
- mdio_write(ioaddr, 31, 0x0002);
- mdio_write(ioaddr, 1, 0x90d0);
- mdio_write(ioaddr, 31, 0x0000);
- return;
- }
-
- if ((tp->mac_version != RTL_GIGA_MAC_VER_02) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_03))
- return;
-
- mdio_write(ioaddr, 31, 0x0001); //w 31 2 0 1
- mdio_write(ioaddr, 21, 0x1000); //w 21 15 0 1000
- mdio_write(ioaddr, 24, 0x65c7); //w 24 15 0 65c7
+ mdio_write(ioaddr, 0x1f, 0x0001); //w 31 2 0 1
+ mdio_write(ioaddr, 0x15, 0x1000); //w 21 15 0 1000
+ mdio_write(ioaddr, 0x18, 0x65c7); //w 24 15 0 65c7
rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) {
@@ -1250,7 +1230,115 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1
rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
}
- mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0
+ mdio_write(ioaddr, 0x1f, 0x0000); //w 31 2 0 0
+}
+
+static void rtl8169sb_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0002 },
+ { 0x01, 0x90d0 },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+static void rtl8168b_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0000 },
+ { 0x10, 0xf41b },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168cp_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0000 },
+ { 0x1d, 0x0f00 },
+ { 0x1f, 0x0002 },
+ { 0x0c, 0x1ec8 },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168c_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0001 },
+ { 0x12, 0x2300 },
+ { 0x1f, 0x0002 },
+ { 0x00, 0x88d4 },
+ { 0x01, 0x82b1 },
+ { 0x03, 0x7002 },
+ { 0x08, 0x9e30 },
+ { 0x09, 0x01f0 },
+ { 0x0a, 0x5500 },
+ { 0x0c, 0x00c8 },
+ { 0x1f, 0x0003 },
+ { 0x12, 0xc096 },
+ { 0x16, 0x000a },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl8168cx_hw_phy_config(void __iomem *ioaddr)
+{
+ struct phy_reg phy_reg_init[] = {
+ { 0x1f, 0x0000 },
+ { 0x12, 0x2300 },
+ { 0x1f, 0x0003 },
+ { 0x16, 0x0f0a },
+ { 0x1f, 0x0000 },
+ { 0x1f, 0x0002 },
+ { 0x0c, 0x7eb8 },
+ { 0x1f, 0x0000 }
+ };
+
+ rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
+static void rtl_hw_phy_config(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ rtl8169_print_mac_version(tp);
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_01:
+ break;
+ case RTL_GIGA_MAC_VER_02:
+ case RTL_GIGA_MAC_VER_03:
+ rtl8169s_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_04:
+ rtl8169sb_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_11:
+ case RTL_GIGA_MAC_VER_12:
+ case RTL_GIGA_MAC_VER_17:
+ rtl8168b_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_18:
+ rtl8168cp_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_19:
+ rtl8168c_hw_phy_config(ioaddr);
+ break;
+ case RTL_GIGA_MAC_VER_20:
+ rtl8168cx_hw_phy_config(ioaddr);
+ break;
+ default:
+ break;
+ }
}
static void rtl8169_phy_timer(unsigned long __opaque)
@@ -1262,7 +1350,6 @@ static void rtl8169_phy_timer(unsigned long __opaque)
unsigned long timeout = RTL8169_PHY_TIMEOUT;
assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
- assert(tp->phy_version < RTL_GIGA_PHY_VER_H);
if (!(tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))
return;
@@ -1297,8 +1384,7 @@ static inline void rtl8169_delete_timer(struct net_device *dev)
struct rtl8169_private *tp = netdev_priv(dev);
struct timer_list *timer = &tp->timer;
- if ((tp->mac_version <= RTL_GIGA_MAC_VER_01) ||
- (tp->phy_version >= RTL_GIGA_PHY_VER_H))
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_01)
return;
del_timer_sync(timer);
@@ -1309,8 +1395,7 @@ static inline void rtl8169_request_timer(struct net_device *dev)
struct rtl8169_private *tp = netdev_priv(dev);
struct timer_list *timer = &tp->timer;
- if ((tp->mac_version <= RTL_GIGA_MAC_VER_01) ||
- (tp->phy_version >= RTL_GIGA_PHY_VER_H))
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_01)
return;
mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT);
@@ -1362,7 +1447,7 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- rtl8169_hw_phy_config(dev);
+ rtl_hw_phy_config(dev);
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8(0x82, 0x01);
@@ -1457,6 +1542,7 @@ static const struct rtl_cfg_info {
unsigned int align;
u16 intr_event;
u16 napi_event;
+ unsigned msi;
} rtl_cfg_infos [] = {
[RTL_CFG_0] = {
.hw_start = rtl_hw_start_8169,
@@ -1464,7 +1550,8 @@ static const struct rtl_cfg_info {
.align = 0,
.intr_event = SYSErr | LinkChg | RxOverflow |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
- .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+ .msi = 0
},
[RTL_CFG_1] = {
.hw_start = rtl_hw_start_8168,
@@ -1472,7 +1559,8 @@ static const struct rtl_cfg_info {
.align = 8,
.intr_event = SYSErr | LinkChg | RxOverflow |
TxErr | TxOK | RxOK | RxErr,
- .napi_event = TxErr | TxOK | RxOK | RxOverflow
+ .napi_event = TxErr | TxOK | RxOK | RxOverflow,
+ .msi = RTL_FEATURE_MSI
},
[RTL_CFG_2] = {
.hw_start = rtl_hw_start_8101,
@@ -1480,10 +1568,39 @@ static const struct rtl_cfg_info {
.align = 8,
.intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
- .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
+ .msi = RTL_FEATURE_MSI
}
};
+/* Cfg9346_Unlock assumed. */
+static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr,
+ const struct rtl_cfg_info *cfg)
+{
+ unsigned msi = 0;
+ u8 cfg2;
+
+ cfg2 = RTL_R8(Config2) & ~MSIEnable;
+ if (cfg->msi) {
+ if (pci_enable_msi(pdev)) {
+ dev_info(&pdev->dev, "no MSI. Back to INTx.\n");
+ } else {
+ cfg2 |= MSIEnable;
+ msi = RTL_FEATURE_MSI;
+ }
+ }
+ RTL_W8(Config2, cfg2);
+ return msi;
+}
+
+static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
+{
+ if (tp->features & RTL_FEATURE_MSI) {
+ pci_disable_msi(pdev);
+ tp->features &= ~RTL_FEATURE_MSI;
+ }
+}
+
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -1596,10 +1713,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Identify chip attached to board */
rtl8169_get_mac_version(tp, ioaddr);
- rtl8169_get_phy_version(tp, ioaddr);
rtl8169_print_mac_version(tp);
- rtl8169_print_phy_version(tp);
for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) {
if (tp->mac_version == rtl_chip_info[i].mac_version)
@@ -1619,6 +1734,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
RTL_W8(Cfg9346, Cfg9346_Unlock);
RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
+ tp->features |= rtl_try_msi(pdev, ioaddr, cfg);
RTL_W8(Cfg9346, Cfg9346_Lock);
if (RTL_R8(PHYstatus) & TBI_Enable) {
@@ -1686,7 +1802,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rc = register_netdev(dev);
if (rc < 0)
- goto err_out_unmap_5;
+ goto err_out_msi_5;
pci_set_drvdata(pdev, dev);
@@ -1709,7 +1825,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
out:
return rc;
-err_out_unmap_5:
+err_out_msi_5:
+ rtl_disable_msi(pdev, tp);
iounmap(ioaddr);
err_out_free_res_4:
pci_release_regions(pdev);
@@ -1730,6 +1847,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
flush_scheduled_work();
unregister_netdev(dev);
+ rtl_disable_msi(pdev, tp);
rtl8169_release_board(pdev, dev, tp->mmio_addr);
pci_set_drvdata(pdev, NULL);
}
@@ -1773,7 +1891,8 @@ static int rtl8169_open(struct net_device *dev)
smp_mb();
- retval = request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED,
+ retval = request_irq(dev->irq, rtl8169_interrupt,
+ (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
dev->name, dev);
if (retval < 0)
goto err_release_ring_2;
@@ -1933,7 +2052,7 @@ static void rtl_hw_start_8169(struct net_device *dev)
if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
(tp->mac_version == RTL_GIGA_MAC_VER_03)) {
- dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. "
+ dprintk("Set MAC Reg C+CR Offset 0xE0. "
"Bit-3 and bit-14 MUST be 1\n");
tp->cp_cmd |= (1 << 14);
}
@@ -2029,7 +2148,8 @@ static void rtl_hw_start_8101(struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr;
struct pci_dev *pdev = tp->pci_dev;
- if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_13) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16)) {
pci_write_config_word(pdev, 0x68, 0x00);
pci_write_config_word(pdev, 0x69, 0x08);
}
@@ -2259,7 +2379,7 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp)
dev_kfree_skb(skb);
tx_skb->skb = NULL;
}
- tp->stats.tx_dropped++;
+ tp->dev->stats.tx_dropped++;
}
}
tp->cur_tx = tp->dirty_tx = 0;
@@ -2310,7 +2430,7 @@ static void rtl8169_reinit_task(struct work_struct *work)
ret = rtl8169_open(dev);
if (unlikely(ret < 0)) {
if (net_ratelimit() && netif_msg_drv(tp)) {
- printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
+ printk(KERN_ERR PFX "%s: reinit failure (status = %d)."
" Rescheduling.\n", dev->name, ret);
}
rtl8169_schedule_work(dev, rtl8169_reinit_task);
@@ -2340,9 +2460,10 @@ static void rtl8169_reset_task(struct work_struct *work)
rtl8169_init_ring_indexes(tp);
rtl_hw_start(dev);
netif_wake_queue(dev);
+ rtl8169_check_link_status(dev, tp, tp->mmio_addr);
} else {
if (net_ratelimit() && netif_msg_intr(tp)) {
- printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
+ printk(KERN_EMERG PFX "%s: Rx buffers shortage\n",
dev->name);
}
rtl8169_schedule_work(dev, rtl8169_reset_task);
@@ -2496,7 +2617,7 @@ err_stop:
netif_stop_queue(dev);
ret = NETDEV_TX_BUSY;
err_update_stats:
- tp->stats.tx_dropped++;
+ dev->stats.tx_dropped++;
goto out;
}
@@ -2571,8 +2692,8 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
if (status & DescOwn)
break;
- tp->stats.tx_bytes += len;
- tp->stats.tx_packets++;
+ dev->stats.tx_bytes += len;
+ dev->stats.tx_packets++;
rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry);
@@ -2672,14 +2793,14 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
"%s: Rx ERROR. status = %08x\n",
dev->name, status);
}
- tp->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (status & (RxRWT | RxRUNT))
- tp->stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
if (status & RxCRC)
- tp->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (status & RxFOVF) {
rtl8169_schedule_work(dev, rtl8169_reset_task);
- tp->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
}
rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
} else {
@@ -2694,8 +2815,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
* sized frames.
*/
if (unlikely(rtl8169_fragmented_frame(status))) {
- tp->stats.rx_dropped++;
- tp->stats.rx_length_errors++;
+ dev->stats.rx_dropped++;
+ dev->stats.rx_length_errors++;
rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
continue;
}
@@ -2719,8 +2840,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
rtl8169_rx_skb(skb);
dev->last_rx = jiffies;
- tp->stats.rx_bytes += pkt_size;
- tp->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_size;
+ dev->stats.rx_packets++;
}
/* Work around for AMD plateform. */
@@ -2881,7 +3002,7 @@ core_down:
rtl8169_asic_down(ioaddr);
/* Update the error counts. */
- tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+ dev->stats.rx_missed_errors += RTL_R32(RxMissed);
RTL_W32(RxMissed, 0);
spin_unlock_irq(&tp->lock);
@@ -2984,7 +3105,9 @@ static void rtl_set_rx_mode(struct net_device *dev)
(tp->mac_version == RTL_GIGA_MAC_VER_12) ||
(tp->mac_version == RTL_GIGA_MAC_VER_13) ||
(tp->mac_version == RTL_GIGA_MAC_VER_14) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_15)) {
+ (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_16) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_17)) {
mc_filter[0] = 0xffffffff;
mc_filter[1] = 0xffffffff;
}
@@ -3011,12 +3134,12 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
if (netif_running(dev)) {
spin_lock_irqsave(&tp->lock, flags);
- tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+ dev->stats.rx_missed_errors += RTL_R32(RxMissed);
RTL_W32(RxMissed, 0);
spin_unlock_irqrestore(&tp->lock, flags);
}
- return &tp->stats;
+ return &dev->stats;
}
#ifdef CONFIG_PM
@@ -3037,14 +3160,15 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
rtl8169_asic_down(ioaddr);
- tp->stats.rx_missed_errors += RTL_R32(RxMissed);
+ dev->stats.rx_missed_errors += RTL_R32(RxMissed);
RTL_W32(RxMissed, 0);
spin_unlock_irq(&tp->lock);
out_pci_suspend:
pci_save_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state),
+ (tp->features & RTL_FEATURE_WOL) ? 1 : 0);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 24cfb6275d9..c27c7d63b6a 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -4271,7 +4271,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
del_timer_sync(&hw->watchdog_timer);
cancel_work_sync(&hw->restart_work);
- for (i = hw->ports; i >= 0; --i)
+ for (i = hw->ports-1; i >= 0; --i)
unregister_netdev(hw->dev[i]);
sky2_write32(hw, B0_IMSK, 0);
@@ -4289,7 +4289,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
- for (i = hw->ports; i >= 0; --i)
+ for (i = hw->ports-1; i >= 0; --i)
free_netdev(hw->dev[i]);
iounmap(hw->regs);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 59d4da2734c..d0bb5b9d212 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1230,7 +1230,7 @@ static void quirk_jmicron_ata(struct pci_dev *pdev)
case PCI_DEVICE_ID_JMICRON_JMB363:
/* Enable dual function mode, AHCI on fn 0, IDE fn1 */
/* Set the class codes correctly and then direct IDE 0 */
- conf1 |= 0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */
+ conf1 |= 0x00C2A1B3; /* Set 0, 1, 4, 5, 7, 8, 13, 15, 17, 22, 23 */
break;
case PCI_DEVICE_ID_JMICRON_JMB368:
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 6141389dcdb..2e6129f13d3 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -115,7 +115,6 @@ obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o
obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o
obj-$(CONFIG_SCSI_MESH) += mesh.o
obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o
-obj-$(CONFIG_SCSI_PLUTO) += pluto.o
obj-$(CONFIG_SCSI_DECNCR) += NCR53C9x.o dec_esp.o
obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o
@@ -123,7 +122,6 @@ obj-$(CONFIG_SCSI_PPA) += ppa.o
obj-$(CONFIG_SCSI_IMM) += imm.o
obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o
obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o
-obj-$(CONFIG_SCSI_FCAL) += fcal.o
obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o
obj-$(CONFIG_SCSI_NSP32) += nsp32.o
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
index c4d17231c82..6d86a9be538 100644
--- a/drivers/scsi/aic7xxx/aic7770.c
+++ b/drivers/scsi/aic7xxx/aic7770.c
@@ -60,8 +60,6 @@
#define ID_OLV_274xD 0x04907783 /* Olivetti OEM (Differential) */
static int aic7770_chip_init(struct ahc_softc *ahc);
-static int aic7770_suspend(struct ahc_softc *ahc);
-static int aic7770_resume(struct ahc_softc *ahc);
static int aha2840_load_seeprom(struct ahc_softc *ahc);
static ahc_device_setup_t ahc_aic7770_VL_setup;
static ahc_device_setup_t ahc_aic7770_EISA_setup;
@@ -155,8 +153,6 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
return (error);
ahc->bus_chip_init = aic7770_chip_init;
- ahc->bus_suspend = aic7770_suspend;
- ahc->bus_resume = aic7770_resume;
error = ahc_reset(ahc, /*reinit*/FALSE);
if (error != 0)
@@ -272,18 +268,6 @@ aic7770_chip_init(struct ahc_softc *ahc)
return (ahc_chip_init(ahc));
}
-static int
-aic7770_suspend(struct ahc_softc *ahc)
-{
- return (ahc_suspend(ahc));
-}
-
-static int
-aic7770_resume(struct ahc_softc *ahc)
-{
- return (ahc_resume(ahc));
-}
-
/*
* Read the 284x SEEPROM.
*/
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 27adbb294ac..ce638aa6005 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1003,8 +1003,15 @@ struct ahd_suspend_channel_state {
uint8_t seqctl;
};
+struct ahd_suspend_pci_state {
+ uint32_t devconfig;
+ uint8_t command;
+ uint8_t csize_lattime;
+};
+
struct ahd_suspend_state {
struct ahd_suspend_channel_state channel[2];
+ struct ahd_suspend_pci_state pci_state;
uint8_t optionmode;
uint8_t dscommand0;
uint8_t dspcistatus;
@@ -1333,6 +1340,8 @@ struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
int ahd_pci_config(struct ahd_softc *,
struct ahd_pci_identity *);
int ahd_pci_test_register_access(struct ahd_softc *);
+void ahd_pci_suspend(struct ahd_softc *);
+void ahd_pci_resume(struct ahd_softc *);
/************************** SCB and SCB queue management **********************/
void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd,
@@ -1343,6 +1352,8 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name);
int ahd_softc_init(struct ahd_softc *);
void ahd_controller_info(struct ahd_softc *ahd, char *buf);
int ahd_init(struct ahd_softc *ahd);
+int ahd_suspend(struct ahd_softc *ahd);
+void ahd_resume(struct ahd_softc *ahd);
int ahd_default_config(struct ahd_softc *ahd);
int ahd_parse_vpddata(struct ahd_softc *ahd,
struct vpd_config *vpd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 05f692bd0ad..a7dd8cdda47 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -7175,7 +7175,6 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
ahd->flags &= ~AHD_ALL_INTERRUPTS;
}
-#if 0
int
ahd_suspend(struct ahd_softc *ahd)
{
@@ -7189,19 +7188,15 @@ ahd_suspend(struct ahd_softc *ahd)
ahd_shutdown(ahd);
return (0);
}
-#endif /* 0 */
-#if 0
-int
+void
ahd_resume(struct ahd_softc *ahd)
{
ahd_reset(ahd, /*reinit*/TRUE);
ahd_intr_enable(ahd, TRUE);
ahd_restart(ahd);
- return (0);
}
-#endif /* 0 */
/************************** Busy Target Table *********************************/
/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 42c0f14a262..2d020405480 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -315,8 +315,8 @@ uint32_t aic79xx_slowcrc;
*/
static char *aic79xx = NULL;
-MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
-MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
+MODULE_AUTHOR("Maintainer: Hannes Reinecke <hare@suse.de>");
+MODULE_DESCRIPTION("Adaptec AIC790X U320 SCSI Host Bus Adapter driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(AIC79XX_DRIVER_VERSION);
module_param(aic79xx, charp, 0444);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index c62ce41f279..66f0259edb6 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -50,6 +50,8 @@ static int ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd,
static int ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
u_long *bus_addr,
uint8_t __iomem **maddr);
+static int ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg);
+static int ahd_linux_pci_dev_resume(struct pci_dev *pdev);
static void ahd_linux_pci_dev_remove(struct pci_dev *pdev);
/* Define the macro locally since it's different for different class of chips.
@@ -86,10 +88,58 @@ MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table);
static struct pci_driver aic79xx_pci_driver = {
.name = "aic79xx",
.probe = ahd_linux_pci_dev_probe,
+#ifdef CONFIG_PM
+ .suspend = ahd_linux_pci_dev_suspend,
+ .resume = ahd_linux_pci_dev_resume,
+#endif
.remove = ahd_linux_pci_dev_remove,
.id_table = ahd_linux_pci_id_table
};
+static int
+ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+ struct ahd_softc *ahd = pci_get_drvdata(pdev);
+ int rc;
+
+ if ((rc = ahd_suspend(ahd)))
+ return rc;
+
+ ahd_pci_suspend(ahd);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ if (mesg.event == PM_EVENT_SUSPEND)
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return rc;
+}
+
+static int
+ahd_linux_pci_dev_resume(struct pci_dev *pdev)
+{
+ struct ahd_softc *ahd = pci_get_drvdata(pdev);
+ int rc;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ if ((rc = pci_enable_device(pdev))) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to enable device after resume (%d)\n", rc);
+ return rc;
+ }
+
+ pci_set_master(pdev);
+
+ ahd_pci_resume(ahd);
+
+ ahd_resume(ahd);
+
+ return rc;
+}
+
static void
ahd_linux_pci_dev_remove(struct pci_dev *pdev)
{
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 0bada0028aa..7a203a90601 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -389,6 +389,33 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
return error;
}
+void
+ahd_pci_suspend(struct ahd_softc *ahd)
+{
+ /*
+ * Save chip register configuration data for chip resets
+ * that occur during runtime and resume events.
+ */
+ ahd->suspend_state.pci_state.devconfig =
+ ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
+ ahd->suspend_state.pci_state.command =
+ ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);
+ ahd->suspend_state.pci_state.csize_lattime =
+ ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1);
+
+}
+
+void
+ahd_pci_resume(struct ahd_softc *ahd)
+{
+ ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,
+ ahd->suspend_state.pci_state.devconfig, /*bytes*/4);
+ ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
+ ahd->suspend_state.pci_state.command, /*bytes*/1);
+ ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME,
+ ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1);
+}
+
/*
* Perform some simple tests that should catch situations where
* our registers are invalidly mapped.
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index e1bd57b9f23..3d4e42d9045 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -962,16 +962,6 @@ struct ahc_softc {
ahc_bus_chip_init_t bus_chip_init;
/*
- * Bus specific suspend routine.
- */
- ahc_bus_suspend_t bus_suspend;
-
- /*
- * Bus specific resume routine.
- */
- ahc_bus_resume_t bus_resume;
-
- /*
* Target mode related state kept on a per enabled lun basis.
* Targets that are not enabled will have null entries.
* As an initiator, we keep one target entry for our initiator
@@ -1153,6 +1143,7 @@ struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t);
int ahc_pci_config(struct ahc_softc *,
struct ahc_pci_identity *);
int ahc_pci_test_register_access(struct ahc_softc *);
+void ahc_pci_resume(struct ahc_softc *ahc);
/*************************** EISA/VL Front End ********************************/
struct aic7770_identity *aic7770_find_device(uint32_t);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 7770befbf50..390b0fc991c 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -335,8 +335,8 @@ static uint32_t aic7xxx_periodic_otag;
*/
static char *aic7xxx = NULL;
-MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
-MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver");
+MODULE_AUTHOR("Maintainer: Hannes Reinecke <hare@suse.de>");
+MODULE_DESCRIPTION("Adaptec AIC77XX/78XX SCSI Host Bus Adapter driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(AIC7XXX_DRIVER_VERSION);
module_param(aic7xxx, charp, 0444);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index ea5687df732..4488946cff2 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -49,6 +49,8 @@ static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
u_long *bus_addr,
uint8_t __iomem **maddr);
+static int ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg);
+static int ahc_linux_pci_dev_resume(struct pci_dev *pdev);
static void ahc_linux_pci_dev_remove(struct pci_dev *pdev);
/* Define the macro locally since it's different for different class of chips.
@@ -133,10 +135,54 @@ MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table);
static struct pci_driver aic7xxx_pci_driver = {
.name = "aic7xxx",
.probe = ahc_linux_pci_dev_probe,
+#ifdef CONFIG_PM
+ .suspend = ahc_linux_pci_dev_suspend,
+ .resume = ahc_linux_pci_dev_resume,
+#endif
.remove = ahc_linux_pci_dev_remove,
.id_table = ahc_linux_pci_id_table
};
+static int
+ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+ struct ahc_softc *ahc = pci_get_drvdata(pdev);
+ int rc;
+
+ if ((rc = ahc_suspend(ahc)))
+ return rc;
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ if (mesg.event == PM_EVENT_SUSPEND)
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return rc;
+}
+
+static int
+ahc_linux_pci_dev_resume(struct pci_dev *pdev)
+{
+ struct ahc_softc *ahc = pci_get_drvdata(pdev);
+ int rc;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ if ((rc = pci_enable_device(pdev))) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to enable device after resume (%d)\n", rc);
+ return rc;
+ }
+
+ pci_set_master(pdev);
+
+ ahc_pci_resume(ahc);
+
+ return (ahc_resume(ahc));
+}
+
static void
ahc_linux_pci_dev_remove(struct pci_dev *pdev)
{
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index 09c8172c9e5..ae35937b805 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -633,8 +633,6 @@ static void write_brdctl(struct ahc_softc *ahc, uint8_t value);
static uint8_t read_brdctl(struct ahc_softc *ahc);
static void ahc_pci_intr(struct ahc_softc *ahc);
static int ahc_pci_chip_init(struct ahc_softc *ahc);
-static int ahc_pci_suspend(struct ahc_softc *ahc);
-static int ahc_pci_resume(struct ahc_softc *ahc);
static int
ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
@@ -791,8 +789,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
ahc->bus_intr = ahc_pci_intr;
ahc->bus_chip_init = ahc_pci_chip_init;
- ahc->bus_suspend = ahc_pci_suspend;
- ahc->bus_resume = ahc_pci_resume;
/* Remeber how the card was setup in case there is no SEEPROM */
if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
@@ -2024,18 +2020,9 @@ ahc_pci_chip_init(struct ahc_softc *ahc)
return (ahc_chip_init(ahc));
}
-static int
-ahc_pci_suspend(struct ahc_softc *ahc)
-{
- return (ahc_suspend(ahc));
-}
-
-static int
+void
ahc_pci_resume(struct ahc_softc *ahc)
{
-
- pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
-
/*
* We assume that the OS has restored our register
* mappings, etc. Just update the config space registers
@@ -2063,7 +2050,6 @@ ahc_pci_resume(struct ahc_softc *ahc)
&sxfrctl1);
ahc_release_seeprom(&sd);
}
- return (ahc_resume(ahc));
}
static int
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
index f06e7035cb3..c0457b8c3b7 100644
--- a/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
+++ b/drivers/scsi/aic7xxx/aicasm/aicasm_macro_scan.l
@@ -66,6 +66,7 @@ static char string_buf[MAX_STR_CONST];
static char *string_buf_ptr;
static int parren_count;
static char buf[255];
+int mmlineno;
%}
WORD [A-Za-z_][-A-Za-z_0-9]*
@@ -76,7 +77,7 @@ MCARG [^(), \t]+
%%
\n {
- ++yylineno;
+ ++mmlineno;
}
\r ;
<ARGLIST>{SPACE} ;
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 4025608d696..8f8db5f0aef 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -8417,7 +8417,7 @@ aic7xxx_alloc(struct scsi_host_template *sht, struct aic7xxx_host *temp)
p->host = host;
p->scb_data = kzalloc(sizeof(scb_data_type), GFP_ATOMIC);
- if (!p->scb_data)
+ if (p->scb_data)
{
scbq_init (&p->scb_data->free_scbs);
}
diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
deleted file mode 100644
index c4e16c0775d..00000000000
--- a/drivers/scsi/fcal.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/* fcal.c: Fibre Channel Arbitrated Loop SCSI host adapter driver.
- *
- * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "../fc4/fcp_impl.h"
-#include "fcal.h"
-
-#include <linux/module.h>
-
-/* #define FCAL_DEBUG */
-
-#define fcal_printk printk ("FCAL %s: ", fc->name); printk
-
-#ifdef FCAL_DEBUG
-#define FCALD(x) fcal_printk x;
-#define FCALND(x) printk ("FCAL: "); printk x;
-#else
-#define FCALD(x)
-#define FCALND(x)
-#endif
-
-static unsigned char alpa2target[] = {
-0x7e, 0x7d, 0x7c, 0xff, 0x7b, 0xff, 0xff, 0xff, 0x7a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79,
-0x78, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x77, 0x76, 0xff, 0xff, 0x75, 0xff, 0x74, 0x73, 0x72,
-0xff, 0xff, 0xff, 0x71, 0xff, 0x70, 0x6f, 0x6e, 0xff, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0xff,
-0xff, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0xff, 0xff, 0x61, 0x60, 0xff, 0x5f, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x5e, 0xff, 0x5d, 0x5c, 0x5b, 0xff, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0xff,
-0xff, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0xff, 0xff, 0x4e, 0x4d, 0xff, 0x4c, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x4b, 0xff, 0x4a, 0x49, 0x48, 0xff, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0xff,
-0xff, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0xff, 0xff, 0x3b, 0x3a, 0xff, 0x39, 0xff, 0xff, 0xff,
-0x38, 0x37, 0x36, 0xff, 0x35, 0xff, 0xff, 0xff, 0x34, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33,
-0x32, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x30, 0xff, 0xff, 0x2f, 0xff, 0x2e, 0x2d, 0x2c,
-0xff, 0xff, 0xff, 0x2b, 0xff, 0x2a, 0x29, 0x28, 0xff, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0xff,
-0xff, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0xff, 0xff, 0x1b, 0x1a, 0xff, 0x19, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x18, 0xff, 0x17, 0x16, 0x15, 0xff, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0xff,
-0xff, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0xff, 0xff, 0x08, 0x07, 0xff, 0x06, 0xff, 0xff, 0xff,
-0x05, 0x04, 0x03, 0xff, 0x02, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
-};
-
-static unsigned char target2alpa[] = {
-0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce,
-0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5, 0xb4, 0xb3,
-0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b,
-0x98, 0x97, 0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79, 0x76, 0x75, 0x74, 0x73,
-0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
-0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c,
-0x3a, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x27, 0x26,
-0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
-};
-
-static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
-
-int fcal_slave_configure(struct scsi_device *device)
-{
- int depth_to_use;
-
- if (device->tagged_supported)
- depth_to_use = /* 254 */ 8;
- else
- depth_to_use = 2;
-
- scsi_adjust_queue_depth(device,
- (device->tagged_supported ?
- MSG_SIMPLE_TAG : 0),
- depth_to_use);
-
- return 0;
-}
-
-/* Detect all FC Arbitrated Loops attached to the machine.
- fc4 module has done all the work for us... */
-int __init fcal_detect(struct scsi_host_template *tpnt)
-{
- int nfcals = 0;
- fc_channel *fc;
- int fcalcount;
- int i;
-
- tpnt->proc_name = "fcal";
- fcalcount = 0;
- for_each_online_fc_channel(fc)
- if (fc->posmap)
- fcalcount++;
- FCALND(("%d channels online\n", fcalcount))
- if (!fcalcount) {
-#if defined(MODULE) && defined(CONFIG_FC4_SOCAL_MODULE) && defined(CONFIG_KMOD)
- request_module("socal");
-
- for_each_online_fc_channel(fc)
- if (fc->posmap)
- fcalcount++;
- if (!fcalcount)
-#endif
- return 0;
- }
- for_each_online_fc_channel(fc) {
- struct Scsi_Host *host;
- long *ages;
- struct fcal *fcal;
-
- if (!fc->posmap) continue;
-
- /* Strange, this is already registered to some other SCSI host, then it cannot be fcal */
- if (fc->scsi_name[0]) continue;
- memcpy (fc->scsi_name, "FCAL", 4);
-
- fc->can_queue = FCAL_CAN_QUEUE;
- fc->rsp_size = 64;
- fc->encode_addr = fcal_encode_addr;
-
- ages = kmalloc (128 * sizeof(long), GFP_KERNEL);
- if (!ages) continue;
-
- host = scsi_register (tpnt, sizeof (struct fcal));
- if (!host)
- {
- kfree(ages);
- continue;
- }
-
- if (!try_module_get(fc->module)) {
- kfree(ages);
- scsi_unregister(host);
- continue;
- }
-
- nfcals++;
-
- fcal = (struct fcal *)host->hostdata;
-
- fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
-
- for (i = 0; i < fc->posmap->len; i++) {
- int status, target, alpa;
-
- alpa = fc->posmap->list[i];
- FCALD(("Sending PLOGI to %02x\n", alpa))
- target = alpa2target[alpa];
- status = fc_do_plogi(fc, alpa, fcal->node_wwn + target,
- fcal->nport_wwn + target);
- FCALD(("PLOGI returned with status %d\n", status))
- if (status != FC_STATUS_OK)
- continue;
- FCALD(("Sending PRLI to %02x\n", alpa))
- status = fc_do_prli(fc, alpa);
- FCALD(("PRLI returned with status %d\n", status))
- if (status == FC_STATUS_OK)
- fcal->map[target] = 1;
- }
-
- host->max_id = 127;
- host->irq = fc->irq;
-#ifdef __sparc_v9__
- host->unchecked_isa_dma = 1;
-#endif
-
- fc->channels = 1;
- fc->targets = 127;
- fc->ages = ages;
- memset (ages, 0, 128 * sizeof(long));
-
- fcal->fc = fc;
-
- FCALD(("Found FCAL\n"))
- }
- if (nfcals)
-#ifdef __sparc__
- printk ("FCAL: Total of %d Sun Enterprise Network Array (A5000 or EX500) channels found\n", nfcals);
-#else
- printk ("FCAL: Total of %d Fibre Channel Arbitrated Loops found\n", nfcals);
-#endif
- return nfcals;
-}
-
-int fcal_release(struct Scsi_Host *host)
-{
- struct fcal *fcal = (struct fcal *)host->hostdata;
- fc_channel *fc = fcal->fc;
-
- module_put(fc->module);
-
- fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
- FCALND((" releasing fcal.\n"));
- kfree (fc->ages);
- FCALND(("released fcal!\n"));
- return 0;
-}
-
-#undef SPRINTF
-#define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); }
-
-int fcal_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout)
-{
- struct fcal *fcal;
- fc_channel *fc;
- char *pos = buffer;
- int i, j;
-
- if (inout) return length;
-
- fcal = (struct fcal *)host->hostdata;
- fc = fcal->fc;
-
-#ifdef __sparc__
- SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s PROM node %x\n", fc->name, fc->dev->prom_node);
-#else
- SPRINTF ("Fibre Channel Arbitrated Loop on %s\n", fc->name);
-#endif
- SPRINTF ("Initiator AL-PA: %02x\n", fc->sid);
-
- SPRINTF ("\nAttached devices:\n");
-
- for (i = 0; i < fc->posmap->len; i++) {
- unsigned char alpa = fc->posmap->list[i];
- unsigned char target;
- u32 *u1, *u2;
-
- target = alpa2target[alpa];
- u1 = (u32 *)&fcal->nport_wwn[target];
- u2 = (u32 *)&fcal->node_wwn[target];
- if (!u1[0] && !u1[1]) {
- SPRINTF (" [AL-PA: %02x] Not responded to PLOGI\n", alpa);
- } else if (!fcal->map[target]) {
- SPRINTF (" [AL-PA: %02x, Port WWN: %08x%08x, Node WWN: %08x%08x] Not responded to PRLI\n",
- alpa, u1[0], u1[1], u2[0], u2[1]);
- } else {
- struct scsi_device *scd;
- shost_for_each_device(scd, host)
- if (scd->id == target) {
- SPRINTF (" [AL-PA: %02x, Id: %02d, Port WWN: %08x%08x, Node WWN: %08x%08x] ",
- alpa, target, u1[0], u1[1], u2[0], u2[1]);
- SPRINTF ("%s ", scsi_device_type(scd->type));
-
- for (j = 0; (j < 8) && (scd->vendor[j] >= 0x20); j++)
- SPRINTF ("%c", scd->vendor[j]);
- SPRINTF (" ");
-
- for (j = 0; (j < 16) && (scd->model[j] >= 0x20); j++)
- SPRINTF ("%c", scd->model[j]);
-
- SPRINTF ("\n");
- }
- }
- }
- SPRINTF ("\n");
-
- *start = buffer + offset;
-
- if ((pos - buffer) < offset)
- return 0;
- else if (pos - buffer - offset < length)
- return pos - buffer - offset;
- else
- return length;
-}
-
-/*
- For FC-AL, we use a simple addressing: we have just one channel 0,
- and all AL-PAs are mapped to targets 0..0x7e
- */
-static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd)
-{
- struct fcal *f;
-
- /* We don't support LUNs yet - I'm not sure if LUN should be in SCSI fcp_cdb, or in second byte of addr[0] */
- if (SCpnt->cmnd[1] & 0xe0) return -EINVAL;
- /* FC-PLDA tells us... */
- memset(addr, 0, 8);
- f = (struct fcal *)SCpnt->device->host->hostdata;
- if (!f->map[SCpnt->device->id])
- return -EINVAL;
- /* Now, determine DID: It will be Native Identifier, so we zero upper
- 2 bytes of the 3 byte DID, lowest byte will be AL-PA */
- fcmd->did = target2alpa[SCpnt->device->id];
- FCALD(("trying DID %06x\n", fcmd->did))
- return 0;
-}
-
-static struct scsi_host_template driver_template = {
- .name = "Fibre Channel Arbitrated Loop",
- .detect = fcal_detect,
- .release = fcal_release,
- .proc_info = fcal_proc_info,
- .queuecommand = fcp_scsi_queuecommand,
- .slave_configure = fcal_slave_configure,
- .can_queue = FCAL_CAN_QUEUE,
- .this_id = -1,
- .sg_tablesize = 1,
- .cmd_per_lun = 1,
- .use_clustering = ENABLE_CLUSTERING,
- .eh_abort_handler = fcp_scsi_abort,
- .eh_device_reset_handler = fcp_scsi_dev_reset,
- .eh_host_reset_handler = fcp_scsi_host_reset,
-};
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/scsi/fcal.h b/drivers/scsi/fcal.h
deleted file mode 100644
index 7ff2c3494f9..00000000000
--- a/drivers/scsi/fcal.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* fcal.h: Generic Fibre Channel Arbitrated Loop SCSI host adapter driver definitions.
- *
- * Copyright (C) 1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#ifndef _FCAL_H
-#define _FCAL_H
-
-#include "../fc4/fcp_impl.h"
-
-struct fcal {
- /* fc must be first */
- fc_channel *fc;
- unsigned char map[128];
- fc_wwn nport_wwn[128];
- fc_wwn node_wwn[128];
-};
-
-/* Arbitrary constant. Cannot be too large, as fc4 layer has limitations
- for a particular channel */
-#define FCAL_CAN_QUEUE 512
-
-int fcal_detect(struct scsi_host_template *);
-int fcal_release(struct Scsi_Host *);
-int fcal_slave_configure(struct scsi_device *);
-
-#endif /* !(_FCAL_H) */
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 5ab3ce76248..b253b8c718d 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4734,7 +4734,7 @@ static struct scsi_host_template gdth_template = {
};
#ifdef CONFIG_ISA
-static int gdth_isa_probe_one(ulong32 isa_bios)
+static int __init gdth_isa_probe_one(ulong32 isa_bios)
{
struct Scsi_Host *shp;
gdth_ha_str *ha;
@@ -4862,7 +4862,7 @@ static int gdth_isa_probe_one(ulong32 isa_bios)
#endif /* CONFIG_ISA */
#ifdef CONFIG_EISA
-static int gdth_eisa_probe_one(ushort eisa_slot)
+static int __init gdth_eisa_probe_one(ushort eisa_slot)
{
struct Scsi_Host *shp;
gdth_ha_str *ha;
@@ -4991,7 +4991,7 @@ static int gdth_eisa_probe_one(ushort eisa_slot)
#endif /* CONFIG_EISA */
#ifdef CONFIG_PCI
-static int gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
{
struct Scsi_Host *shp;
gdth_ha_str *ha;
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 112ab6abe62..24271a871b8 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -345,6 +345,12 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
shost->active_mode = sht->supported_mode;
shost->use_sg_chaining = sht->use_sg_chaining;
+ if (sht->supported_mode == MODE_UNKNOWN)
+ /* means we didn't set it ... default to INITIATOR */
+ shost->active_mode = MODE_INITIATOR;
+ else
+ shost->active_mode = sht->supported_mode;
+
if (sht->max_host_blocked)
shost->max_host_blocked = sht->max_host_blocked;
else
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 8515054cdf7..0844331abb8 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -375,8 +375,9 @@ static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag)
scp->result = SAM_STAT_CHECK_CONDITION;
memset(&scp->sense_buffer,
0, sizeof(scp->sense_buffer));
- memcpy(&scp->sense_buffer,
- &req->sg_list, le32_to_cpu(req->dataxfer_length));
+ memcpy(&scp->sense_buffer, &req->sg_list,
+ min(sizeof(scp->sense_buffer),
+ le32_to_cpu(req->dataxfer_length)));
break;
default:
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 22d40fd5845..4c4465d39a1 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -665,7 +665,7 @@ static void initio_init(struct initio_host * host, u8 *bios_addr)
host->max_tags[i] = 0xFF;
} /* for */
printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
- host->addr, host->irq,
+ host->addr, host->pci_dev->irq,
host->bios_addr, host->scsi_id);
/* Reset SCSI Bus */
if (host->config & HCC_SCSI_RESET) {
@@ -2891,6 +2891,8 @@ static int initio_probe_one(struct pci_dev *pdev,
goto out_release_region;
}
+ host->pci_dev = pdev;
+
host->num_scbs = num_scb;
host->scb = scb;
host->next_pending = scb;
@@ -2905,6 +2907,7 @@ static int initio_probe_one(struct pci_dev *pdev,
host->scb_end = tmp;
host->first_avail = scb;
host->last_avail = prev;
+ spin_lock_init(&host->avail_lock);
initio_init(host, phys_to_virt(bios_seg << 4));
@@ -2928,7 +2931,6 @@ static int initio_probe_one(struct pci_dev *pdev,
}
pci_set_drvdata(pdev, shost);
- host->pci_dev = pdev;
error = scsi_add_host(shost, &pdev->dev);
if (error)
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 149fdd25f8e..d6a98bc970f 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -901,7 +901,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
}
}
- vport->disc_trc = kmzlloc(
+ vport->disc_trc = kzalloc(
(sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc),
GFP_KERNEL);
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
deleted file mode 100644
index 0363c1cd68c..00000000000
--- a/drivers/scsi/pluto.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/* pluto.c: SparcSTORAGE Array SCSI host adapter driver.
- *
- * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- */
-
-#include <linux/completion.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
-#include <asm/irq.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "../fc4/fcp_impl.h"
-#include "pluto.h"
-
-#include <linux/module.h>
-
-#define RQ_SCSI_BUSY 0xffff
-#define RQ_SCSI_DONE 0xfffe
-
-/* #define PLUTO_DEBUG */
-
-#define pluto_printk printk ("PLUTO %s: ", fc->name); printk
-
-#ifdef PLUTO_DEBUG
-#define PLD(x) pluto_printk x;
-#define PLND(x) printk ("PLUTO: "); printk x;
-#else
-#define PLD(x)
-#define PLND(x)
-#endif
-
-static struct ctrl_inquiry {
- struct Scsi_Host host;
- struct pluto pluto;
- Scsi_Cmnd cmd;
- char inquiry[256];
- fc_channel *fc;
-} *fcs __initdata;
-static int fcscount __initdata = 0;
-static atomic_t fcss __initdata = ATOMIC_INIT(0);
-static DECLARE_COMPLETION(fc_detect_complete);
-
-static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
-
-static void __init pluto_detect_done(Scsi_Cmnd *SCpnt)
-{
- /* Do nothing */
-}
-
-static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt)
-{
- PLND(("Detect done %08lx\n", (long)SCpnt))
- if (atomic_dec_and_test (&fcss))
- complete(&fc_detect_complete);
-}
-
-int pluto_slave_configure(struct scsi_device *device)
-{
- int depth_to_use;
-
- if (device->tagged_supported)
- depth_to_use = /* 254 */ 8;
- else
- depth_to_use = 2;
-
- scsi_adjust_queue_depth(device,
- (device->tagged_supported ?
- MSG_SIMPLE_TAG : 0),
- depth_to_use);
-
- return 0;
-}
-
-/* Detect all SSAs attached to the machine.
- To be fast, do it on all online FC channels at the same time. */
-int __init pluto_detect(struct scsi_host_template *tpnt)
-{
- int i, retry, nplutos;
- fc_channel *fc;
- struct scsi_device dev;
-
- tpnt->proc_name = "pluto";
- fcscount = 0;
- for_each_online_fc_channel(fc) {
- if (!fc->posmap)
- fcscount++;
- }
- PLND(("%d channels online\n", fcscount))
- if (!fcscount) {
-#if defined(MODULE) && defined(CONFIG_FC4_SOC_MODULE) && defined(CONFIG_KMOD)
- request_module("soc");
-
- for_each_online_fc_channel(fc) {
- if (!fc->posmap)
- fcscount++;
- }
- if (!fcscount)
-#endif
- return 0;
- }
- fcs = kcalloc(fcscount, sizeof (struct ctrl_inquiry), GFP_DMA);
- if (!fcs) {
- printk ("PLUTO: Not enough memory to probe\n");
- return 0;
- }
-
- memset (&dev, 0, sizeof(dev));
- atomic_set (&fcss, fcscount);
-
- i = 0;
- for_each_online_fc_channel(fc) {
- Scsi_Cmnd *SCpnt;
- struct Scsi_Host *host;
- struct pluto *pluto;
-
- if (i == fcscount) break;
- if (fc->posmap) continue;
-
- PLD(("trying to find SSA\n"))
-
- /* If this is already registered to some other SCSI host, then it cannot be pluto */
- if (fc->scsi_name[0]) continue;
- memcpy (fc->scsi_name, "SSA", 4);
-
- fcs[i].fc = fc;
-
- fc->can_queue = PLUTO_CAN_QUEUE;
- fc->rsp_size = 64;
- fc->encode_addr = pluto_encode_addr;
-
- fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
-
- SCpnt = &(fcs[i].cmd);
- host = &(fcs[i].host);
- pluto = (struct pluto *)host->hostdata;
-
- pluto->fc = fc;
-
- SCpnt->cmnd[0] = INQUIRY;
- SCpnt->cmnd[4] = 255;
-
- /* FC layer requires this, so that SCpnt->device->tagged_supported is initially 0 */
- SCpnt->device = &dev;
- dev.host = host;
-
- SCpnt->cmd_len = COMMAND_SIZE(INQUIRY);
-
- SCpnt->request->cmd_flags &= ~REQ_STARTED;
-
- SCpnt->request_bufflen = 256;
- SCpnt->request_buffer = fcs[i].inquiry;
- PLD(("set up %d %08lx\n", i, (long)SCpnt))
- i++;
- }
-
- for (retry = 0; retry < 5; retry++) {
- for (i = 0; i < fcscount; i++) {
- if (!fcs[i].fc) break;
- if (!(fcs[i].cmd.request->cmd_flags & REQ_STARTED)) {
- fcs[i].cmd.request->cmd_flags |= REQ_STARTED;
- disable_irq(fcs[i].fc->irq);
- PLND(("queuecommand %d %d\n", retry, i))
- fcp_scsi_queuecommand (&(fcs[i].cmd),
- pluto_detect_scsi_done);
- enable_irq(fcs[i].fc->irq);
- }
- }
-
- wait_for_completion_timeout(&fc_detect_complete, 10 * HZ);
- PLND(("Woken up\n"))
- if (!atomic_read(&fcss))
- break; /* All fc channels have answered us */
- }
-
- PLND(("Finished search\n"))
- for (i = 0, nplutos = 0; i < fcscount; i++) {
- Scsi_Cmnd *SCpnt;
-
- if (!(fc = fcs[i].fc)) break;
-
- SCpnt = &(fcs[i].cmd);
-
- /* Let FC mid-level free allocated resources */
- pluto_detect_scsi_done(SCpnt);
-
- if (!SCpnt->result) {
- struct pluto_inquiry *inq;
- struct pluto *pluto;
- struct Scsi_Host *host;
-
- inq = (struct pluto_inquiry *)fcs[i].inquiry;
-
- if ((inq->dtype & 0x1f) == TYPE_PROCESSOR &&
- !strncmp (inq->vendor_id, "SUN", 3) &&
- !strncmp (inq->product_id, "SSA", 3)) {
- char *p;
- long *ages;
-
- ages = kcalloc((inq->channels + 1) * inq->targets, sizeof(long), GFP_KERNEL);
- if (!ages) continue;
-
- host = scsi_register (tpnt, sizeof (struct pluto));
- if(!host)
- {
- kfree(ages);
- continue;
- }
-
- if (!try_module_get(fc->module)) {
- kfree(ages);
- scsi_unregister(host);
- continue;
- }
-
- nplutos++;
-
- pluto = (struct pluto *)host->hostdata;
-
- host->max_id = inq->targets;
- host->max_channel = inq->channels;
- host->irq = fc->irq;
-
- fc->channels = inq->channels + 1;
- fc->targets = inq->targets;
- fc->ages = ages;
-
- pluto->fc = fc;
- memcpy (pluto->rev_str, inq->revision, 4);
- pluto->rev_str[4] = 0;
- p = strchr (pluto->rev_str, ' ');
- if (p) *p = 0;
- memcpy (pluto->fw_rev_str, inq->fw_revision, 4);
- pluto->fw_rev_str[4] = 0;
- p = strchr (pluto->fw_rev_str, ' ');
- if (p) *p = 0;
- memcpy (pluto->serial_str, inq->serial, 12);
- pluto->serial_str[12] = 0;
- p = strchr (pluto->serial_str, ' ');
- if (p) *p = 0;
-
- PLD(("Found SSA rev %s fw rev %s serial %s %dx%d\n", pluto->rev_str, pluto->fw_rev_str, pluto->serial_str, host->max_channel, host->max_id))
- } else
- fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
- } else
- fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
- }
- kfree(fcs);
- if (nplutos)
- printk ("PLUTO: Total of %d SparcSTORAGE Arrays found\n", nplutos);
- return nplutos;
-}
-
-int pluto_release(struct Scsi_Host *host)
-{
- struct pluto *pluto = (struct pluto *)host->hostdata;
- fc_channel *fc = pluto->fc;
-
- module_put(fc->module);
-
- fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
- PLND((" releasing pluto.\n"));
- kfree (fc->ages);
- PLND(("released pluto!\n"));
- return 0;
-}
-
-const char *pluto_info(struct Scsi_Host *host)
-{
- static char buf[128], *p;
- struct pluto *pluto = (struct pluto *) host->hostdata;
-
- sprintf(buf, "SUN SparcSTORAGE Array %s fw %s serial %s %dx%d on %s",
- pluto->rev_str, pluto->fw_rev_str, pluto->serial_str,
- host->max_channel, host->max_id, pluto->fc->name);
-#ifdef __sparc__
- p = strchr(buf, 0);
- sprintf(p, " PROM node %x", pluto->fc->dev->prom_node);
-#endif
- return buf;
-}
-
-/* SSA uses this FC4S addressing:
- switch (addr[0])
- {
- case 0: CONTROLLER - All of addr[1]..addr[3] has to be 0
- case 1: SINGLE DISK - addr[1] channel, addr[2] id, addr[3] 0
- case 2: DISK GROUP - ???
- }
-
- So that SCSI mid-layer can access to these, we reserve
- channel 0 id 0 lun 0 for CONTROLLER
- and channels 1 .. max_channel are normal single disks.
- */
-static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd)
-{
- PLND(("encode addr %d %d %d\n", SCpnt->device->channel, SCpnt->device->id, SCpnt->cmnd[1] & 0xe0))
- /* We don't support LUNs - neither does SSA :) */
- if (SCpnt->cmnd[1] & 0xe0)
- return -EINVAL;
- if (!SCpnt->device->channel) {
- if (SCpnt->device->id)
- return -EINVAL;
- memset (addr, 0, 4 * sizeof(u16));
- } else {
- addr[0] = 1;
- addr[1] = SCpnt->device->channel - 1;
- addr[2] = SCpnt->device->id;
- addr[3] = 0;
- }
- /* We're Point-to-Point, so target it to the default DID */
- fcmd->did = fc->did;
- PLND(("trying %04x%04x%04x%04x\n", addr[0], addr[1], addr[2], addr[3]))
- return 0;
-}
-
-static struct scsi_host_template driver_template = {
- .name = "Sparc Storage Array 100/200",
- .detect = pluto_detect,
- .release = pluto_release,
- .info = pluto_info,
- .queuecommand = fcp_scsi_queuecommand,
- .slave_configure = pluto_slave_configure,
- .can_queue = PLUTO_CAN_QUEUE,
- .this_id = -1,
- .sg_tablesize = 1,
- .cmd_per_lun = 1,
- .use_clustering = ENABLE_CLUSTERING,
- .eh_abort_handler = fcp_scsi_abort,
- .eh_device_reset_handler = fcp_scsi_dev_reset,
- .eh_host_reset_handler = fcp_scsi_host_reset,
-};
-
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/scsi/pluto.h b/drivers/scsi/pluto.h
deleted file mode 100644
index 5da20616ac3..00000000000
--- a/drivers/scsi/pluto.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* pluto.h: SparcSTORAGE Array SCSI host adapter driver definitions.
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#ifndef _PLUTO_H
-#define _PLUTO_H
-
-#include "../fc4/fcp_impl.h"
-
-struct pluto {
- /* This must be first */
- fc_channel *fc;
- char rev_str[5];
- char fw_rev_str[5];
- char serial_str[13];
-};
-
-struct pluto_inquiry {
- u8 dtype;
- u8 removable:1, qualifier:7;
- u8 iso:2, ecma:3, ansi:3;
- u8 aenc:1, trmiop:1, :2, rdf:4;
- u8 len;
- u8 xxx1;
- u8 xxx2;
- u8 reladdr:1, wbus32:1, wbus16:1, sync:1, linked:1, :1, cmdque:1, softreset:1;
- u8 vendor_id[8];
- u8 product_id[16];
- u8 revision[4];
- u8 fw_revision[4];
- u8 serial[12];
- u8 xxx3[2];
- u8 channels;
- u8 targets;
-};
-
-/* This is the max number of outstanding SCSI commands per pluto */
-#define PLUTO_CAN_QUEUE 254
-
-int pluto_detect(struct scsi_host_template *);
-int pluto_release(struct Scsi_Host *);
-const char * pluto_info(struct Scsi_Host *);
-int pluto_slave_configure(struct scsi_device *);
-
-#endif /* !(_PLUTO_H) */
-
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 76089cf55f4..3aeb68bcb7a 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -4310,7 +4310,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
printk(KERN_WARNING "scsi(%li): Unable to set a "
"suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
- goto error_free_irq;
+ goto error_put_host;
}
} else
dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n",
@@ -4320,7 +4320,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
printk(KERN_WARNING "scsi(%li): Unable to set a "
"suitable DMA mask - aborting\n", ha->host_no);
error = -ENODEV;
- goto error_free_irq;
+ goto error_put_host;
}
#endif
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
index 59915fb7030..ff2c363ead2 100644
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -91,8 +91,8 @@
#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS + 2)
/* ISP request and response entry counts (37-65535) */
-#define REQUEST_ENTRY_CNT 256 /* Number of request entries. */
-#define RESPONSE_ENTRY_CNT 16 /* Number of response entries. */
+#define REQUEST_ENTRY_CNT 255 /* Number of request entries. */
+#define RESPONSE_ENTRY_CNT 63 /* Number of response entries. */
/*
* SCSI Request Block structure (sp) that is placed
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 05fa7796a55..fb388b8c07c 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -114,7 +114,6 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
- unsigned long flags;
uint16_t cnt;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
@@ -144,11 +143,9 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
}
/* Write NVRAM. */
- spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base,
count);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
@@ -397,16 +394,13 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
- unsigned long flags;
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
return 0;
/* Write NVRAM. */
- spin_lock_irqsave(&ha->hardware_lock, flags);
ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count);
ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
return count;
}
@@ -544,6 +538,9 @@ qla2x00_serial_num_show(struct class_device *cdev, char *buf)
scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev));
uint32_t sn;
+ if (IS_FWI2_CAPABLE(ha))
+ return snprintf(buf, PAGE_SIZE, "\n");
+
sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
sn % 100000);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 1900fbf6cd7..04e8cbca4c0 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2271,6 +2271,7 @@ typedef struct scsi_qla_host {
spinlock_t hardware_lock ____cacheline_aligned;
+ int bars;
device_reg_t __iomem *iobase; /* Base I/O address */
unsigned long pio_address;
unsigned long pio_length;
diff --git a/drivers/scsi/qla2xxx/qla_devtbl.h b/drivers/scsi/qla2xxx/qla_devtbl.h
index dd435410dfa..d78d35e681a 100644
--- a/drivers/scsi/qla2xxx/qla_devtbl.h
+++ b/drivers/scsi/qla2xxx/qla_devtbl.h
@@ -1,4 +1,4 @@
-#define QLA_MODEL_NAMES 0x57
+#define QLA_MODEL_NAMES 0x5C
/*
* Adapter model names and descriptions.
@@ -91,4 +91,9 @@ static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = {
" ", " ", /* 0x154 */
"QLE220", "PCI-Express to 4Gb FC, Single Channel", /* 0x155 */
"QLE220", "PCI-Express to 4Gb FC, Single Channel", /* 0x156 */
+ " ", " ", /* 0x157 */
+ " ", " ", /* 0x158 */
+ " ", " ", /* 0x159 */
+ " ", " ", /* 0x15a */
+ "QME2472", "Dell BS PCI-Express to 4Gb FC, Dual Channel", /* 0x15b */
};
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 7f6a89bd94f..024c662ec34 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -525,7 +525,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha)
/* Check for pending interrupts. */
/* During init we issue marker directly */
- if (!ha->marker_needed)
+ if (!ha->marker_needed && !ha->flags.init_done)
qla2x00_poll(ha);
spin_lock_irq(&ha->hardware_lock);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index c4768c4f399..1104bd2eed4 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1012,8 +1012,14 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
case CS_DATA_UNDERRUN:
resid = resid_len;
/* Use F/W calculated residual length. */
- if (IS_FWI2_CAPABLE(ha))
+ if (IS_FWI2_CAPABLE(ha)) {
+ if (scsi_status & SS_RESIDUAL_UNDER &&
+ resid != fw_resid_len) {
+ scsi_status &= ~SS_RESIDUAL_UNDER;
+ lscsi_status = 0;
+ }
resid = fw_resid_len;
+ }
if (scsi_status & SS_RESIDUAL_UNDER) {
scsi_set_resid(cp, resid);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index c53ec67c47f..ccd662a6f5d 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -252,7 +252,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp)
/* Clean up */
ha->mcp = NULL;
- if (!abort_active) {
+ if (abort_active || !io_lock_on) {
DEBUG11(printk("%s(%ld): checking for additional resp "
"interrupt.\n", __func__, ha->host_no));
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 0351d380c2d..a5bcf1f390b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1482,6 +1482,17 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
unsigned long pio, pio_len, pio_flags;
unsigned long mmio, mmio_len, mmio_flags;
+ if (pci_request_selected_regions(ha->pdev, ha->bars,
+ QLA2XXX_DRIVER_NAME)) {
+ qla_printk(KERN_WARNING, ha,
+ "Failed to reserve PIO/MMIO regions (%s)\n",
+ pci_name(ha->pdev));
+
+ goto iospace_error_exit;
+ }
+ if (!(ha->bars & 1))
+ goto skip_pio;
+
/* We only need PIO for Flash operations on ISP2312 v2 chips. */
pio = pci_resource_start(ha->pdev, 0);
pio_len = pci_resource_len(ha->pdev, 0);
@@ -1499,7 +1510,10 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
pci_name(ha->pdev));
pio = 0;
}
+ ha->pio_address = pio;
+ ha->pio_length = pio_len;
+skip_pio:
/* Use MMIO operations for all accesses. */
mmio = pci_resource_start(ha->pdev, 1);
mmio_len = pci_resource_len(ha->pdev, 1);
@@ -1518,16 +1532,6 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
goto iospace_error_exit;
}
- if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) {
- qla_printk(KERN_WARNING, ha,
- "Failed to reserve PIO/MMIO regions (%s)\n",
- pci_name(ha->pdev));
-
- goto iospace_error_exit;
- }
-
- ha->pio_address = pio;
- ha->pio_length = pio_len;
ha->iobase = ioremap(mmio, MIN_IOBASE_LEN);
if (!ha->iobase) {
qla_printk(KERN_ERR, ha,
@@ -1579,21 +1583,26 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
char pci_info[30];
char fw_str[30];
struct scsi_host_template *sht;
+ int bars;
- if (pci_enable_device(pdev))
- goto probe_out;
-
- if (pci_find_aer_capability(pdev))
- if (pci_enable_pcie_error_reporting(pdev))
- goto probe_out;
-
+ bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
sht = &qla2x00_driver_template;
if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
- pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532)
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
+ bars = pci_select_bars(pdev, IORESOURCE_MEM);
sht = &qla24xx_driver_template;
+ }
+
+ if (pci_enable_device_bars(pdev, bars))
+ goto probe_out;
+
+ if (pci_find_aer_capability(pdev))
+ if (pci_enable_pcie_error_reporting(pdev))
+ goto probe_out;
+
host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
if (host == NULL) {
printk(KERN_WARNING
@@ -1610,6 +1619,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->host_no = host->host_no;
sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
ha->parent = NULL;
+ ha->bars = bars;
/* Set ISP-type information. */
qla2x00_set_isp_flags(ha);
@@ -1880,7 +1890,7 @@ qla2x00_free_device(scsi_qla_host_t *ha)
/* release io space registers */
if (ha->iobase)
iounmap(ha->iobase);
- pci_release_regions(ha->pdev);
+ pci_release_selected_regions(ha->pdev, ha->bars);
}
static inline void
@@ -2890,7 +2900,7 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
scsi_qla_host_t *ha = pci_get_drvdata(pdev);
- if (pci_enable_device(pdev)) {
+ if (pci_enable_device_bars(pdev, ha->bars)) {
qla_printk(KERN_WARNING, ha,
"Can't re-enable PCI device after reset.\n");
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 40b059fc198..ad2fa01bd23 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -7,6 +7,7 @@
#include "qla_def.h"
#include <linux/delay.h>
+#include <linux/vmalloc.h>
#include <asm/uaccess.h>
static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t);
@@ -642,7 +643,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
}
/* Go with burst-write. */
- if (optrom && (liter + OPTROM_BURST_DWORDS) < dwords) {
+ if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) {
/* Copy data to DMA'ble buffer. */
for (miter = 0, s = optrom, d = dwptr;
miter < OPTROM_BURST_DWORDS; miter++, s++, d++)
@@ -656,7 +657,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
"Unable to burst-write optrom segment "
"(%x/%x/%llx).\n", ret,
flash_data_to_access_addr(faddr),
- optrom_dma);
+ (unsigned long long)optrom_dma);
qla_printk(KERN_WARNING, ha,
"Reverting to slow-write.\n");
@@ -745,9 +746,11 @@ qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
int ret, stat;
uint32_t i;
uint16_t *wptr;
+ unsigned long flags;
ret = QLA_SUCCESS;
+ spin_lock_irqsave(&ha->hardware_lock, flags);
qla2x00_lock_nvram_access(ha);
/* Disable NVRAM write-protection. */
@@ -764,6 +767,7 @@ qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
qla2x00_set_nvram_protection(ha, stat);
qla2x00_unlock_nvram_access(ha);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ret;
}
@@ -776,9 +780,11 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t i;
uint32_t *dwptr;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ unsigned long flags;
ret = QLA_SUCCESS;
+ spin_lock_irqsave(&ha->hardware_lock, flags);
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
@@ -812,6 +818,7 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ret;
}
@@ -836,8 +843,20 @@ int
qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t bytes)
{
- return qla24xx_write_flash_data(ha, (uint32_t *)buf,
- FA_VPD_NVRAM_ADDR | naddr, bytes >> 2);
+#define RMW_BUFFER_SIZE (64 * 1024)
+ uint8_t *dbuf;
+
+ dbuf = vmalloc(RMW_BUFFER_SIZE);
+ if (!dbuf)
+ return QLA_MEMORY_ALLOC_FAILED;
+ ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2,
+ RMW_BUFFER_SIZE);
+ memcpy(dbuf + (naddr << 2), buf, bytes);
+ ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2,
+ RMW_BUFFER_SIZE);
+ vfree(dbuf);
+
+ return QLA_SUCCESS;
}
static inline void
@@ -1853,7 +1872,8 @@ qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
qla_printk(KERN_WARNING, ha,
"Unable to burst-read optrom segment "
"(%x/%x/%llx).\n", rval,
- flash_data_to_access_addr(faddr), optrom_dma);
+ flash_data_to_access_addr(faddr),
+ (unsigned long long)optrom_dma);
qla_printk(KERN_WARNING, ha,
"Reverting to slow-read.\n");
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 2d551a3006f..ae6f7a2fb19 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.02.00-k4"
+#define QLA2XXX_VERSION "8.02.00-k5"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index d29f8464b74..ebaca4ca4a1 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -24,7 +24,6 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
-#include <linux/scatterlist.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index daed37df00b..d531ceeb0d8 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -209,11 +209,13 @@ show_shost_mode(unsigned int mode, char *buf)
static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *buf)
{
struct Scsi_Host *shost = class_to_shost(class_dev);
+ unsigned int supported_mode = shost->hostt->supported_mode;
- if (shost->hostt->supported_mode == MODE_UNKNOWN)
- return snprintf(buf, 20, "unknown\n");
- else
- return show_shost_mode(shost->hostt->supported_mode, buf);
+ if (supported_mode == MODE_UNKNOWN)
+ /* by default this should be initiator */
+ supported_mode = MODE_INITIATOR;
+
+ return show_shost_mode(supported_mode, buf);
}
static CLASS_DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
diff --git a/drivers/scsi/sym53c8xx_2/sym53c8xx.h b/drivers/scsi/sym53c8xx_2/sym53c8xx.h
index 7519728dfc3..62d29cfac9e 100644
--- a/drivers/scsi/sym53c8xx_2/sym53c8xx.h
+++ b/drivers/scsi/sym53c8xx_2/sym53c8xx.h
@@ -127,7 +127,6 @@ struct sym_driver_setup {
u_char settle_delay;
u_char use_nvram;
u_long excludes[8];
- char tag_ctrl[100];
};
#define SYM_SETUP_MAX_TAG sym_driver_setup.max_tag
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
index 9916a2a2255..190770bdc19 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c
@@ -104,8 +104,9 @@ static struct sym_fwz_ofs sym_fw2z_ofs = {
* Patch routine for firmware #1.
*/
static void
-sym_fw1_patch(struct sym_hcb *np)
+sym_fw1_patch(struct Scsi_Host *shost)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
struct sym_fw1a_scr *scripta0;
struct sym_fw1b_scr *scriptb0;
@@ -145,8 +146,11 @@ sym_fw1_patch(struct sym_hcb *np)
* Patch routine for firmware #2.
*/
static void
-sym_fw2_patch(struct sym_hcb *np)
+sym_fw2_patch(struct Scsi_Host *shost)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ struct sym_hcb *np = sym_data->ncb;
struct sym_fw2a_scr *scripta0;
struct sym_fw2b_scr *scriptb0;
@@ -167,7 +171,7 @@ sym_fw2_patch(struct sym_hcb *np)
* Remove useless 64 bit DMA specific SCRIPTS,
* when this feature is not available.
*/
- if (!np->use_dac) {
+ if (!use_dac(np)) {
scripta0->is_dmap_dirty[0] = cpu_to_scr(SCR_NO_OP);
scripta0->is_dmap_dirty[1] = 0;
scripta0->is_dmap_dirty[2] = cpu_to_scr(SCR_NO_OP);
@@ -205,14 +209,14 @@ sym_fw2_patch(struct sym_hcb *np)
* Remove a couple of work-arounds specific to C1010 if
* they are not desirable. See `sym_fw2.h' for more details.
*/
- if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 &&
- np->revision_id < 0x1 &&
+ if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_66 &&
+ pdev->revision < 0x1 &&
np->pciclk_khz < 60000)) {
scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
scripta0->datao_phase[1] = cpu_to_scr(0);
}
- if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
- /* np->revision_id < 0xff */ 1)) {
+ if (!(pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 /* &&
+ pdev->revision < 0xff */)) {
scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
scripta0->sel_done[1] = cpu_to_scr(0);
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.h b/drivers/scsi/sym53c8xx_2/sym_fw.h
index 66ec35beab5..ae7e0f9e93f 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.h
@@ -143,7 +143,7 @@ struct sym_fw {
*z_ofs; /* Useful offsets in script Z */
/* Setup and patch methods for this firmware */
void (*setup)(struct sym_hcb *, struct sym_fw *);
- void (*patch)(struct sym_hcb *);
+ void (*patch)(struct Scsi_Host *);
};
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index db03c4c8ec1..0f74aba5b23 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -39,7 +39,6 @@
*/
#include <linux/ctype.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
@@ -54,16 +53,12 @@
#define NAME53C "sym53c"
#define NAME53C8XX "sym53c8xx"
-#define IRQ_FMT "%d"
-#define IRQ_PRM(x) (x)
-
struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
unsigned int sym_debug_flags = 0;
static char *excl_string;
static char *safe_string;
module_param_named(cmd_per_lun, sym_driver_setup.max_tag, ushort, 0);
-module_param_string(tag_ctrl, sym_driver_setup.tag_ctrl, 100, 0);
module_param_named(burst, sym_driver_setup.burst_order, byte, 0);
module_param_named(led, sym_driver_setup.scsi_led, byte, 0);
module_param_named(diff, sym_driver_setup.scsi_diff, byte, 0);
@@ -78,7 +73,6 @@ module_param_named(excl, excl_string, charp, 0);
module_param_named(safe, safe_string, charp, 0);
MODULE_PARM_DESC(cmd_per_lun, "The maximum number of tags to use by default");
-MODULE_PARM_DESC(tag_ctrl, "More detailed control over tags per LUN");
MODULE_PARM_DESC(burst, "Maximum burst. 0 to disable, 255 to read from registers");
MODULE_PARM_DESC(led, "Set to 1 to enable LED support");
MODULE_PARM_DESC(diff, "0 for no differential mode, 1 for BIOS, 2 for always, 3 for not GPIO3");
@@ -134,56 +128,26 @@ static struct scsi_transport_template *sym2_transport_template = NULL;
* Driver private area in the SCSI command structure.
*/
struct sym_ucmd { /* Override the SCSI pointer structure */
- dma_addr_t data_mapping;
- unsigned char data_mapped;
- unsigned char to_do; /* For error handling */
- void (*old_done)(struct scsi_cmnd *); /* For error handling */
- struct completion *eh_done; /* For error handling */
+ struct completion *eh_done; /* SCSI error handling */
};
#define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp))
#define SYM_SOFTC_PTR(cmd) sym_get_hcb(cmd->device->host)
-static void __unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
- if (SYM_UCMD_PTR(cmd)->data_mapped)
- scsi_dma_unmap(cmd);
-
- SYM_UCMD_PTR(cmd)->data_mapped = 0;
-}
-
-static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
- int use_sg;
-
- use_sg = scsi_dma_map(cmd);
- if (use_sg > 0) {
- SYM_UCMD_PTR(cmd)->data_mapped = 2;
- SYM_UCMD_PTR(cmd)->data_mapping = use_sg;
- }
-
- return use_sg;
-}
-
-#define unmap_scsi_data(np, cmd) \
- __unmap_scsi_data(np->s.device, cmd)
-#define map_scsi_sg_data(np, cmd) \
- __map_scsi_sg_data(np->s.device, cmd)
/*
* Complete a pending CAM CCB.
*/
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *cmd)
{
- unmap_scsi_data(np, cmd);
- cmd->scsi_done(cmd);
-}
+ struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
+ BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd));
-static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *cmd, int cam_status)
-{
- sym_set_cam_status(cmd, cam_status);
- sym_xpt_done(np, cmd);
-}
+ if (ucmd->eh_done)
+ complete(ucmd->eh_done);
+ scsi_dma_unmap(cmd);
+ cmd->scsi_done(cmd);
+}
/*
* Tell the SCSI layer about a BUS RESET.
@@ -199,14 +163,6 @@ void sym_xpt_async_bus_reset(struct sym_hcb *np)
}
/*
- * Tell the SCSI layer about a BUS DEVICE RESET message sent.
- */
-void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target)
-{
- printf_notice("%s: TARGET %d has been reset.\n", sym_name(np), target);
-}
-
-/*
* Choose the more appropriate CAM status if
* the IO encountered an extended error.
*/
@@ -307,14 +263,14 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd
cp->data_len = 0;
- use_sg = map_scsi_sg_data(np, cmd);
+ use_sg = scsi_dma_map(cmd);
if (use_sg > 0) {
struct scatterlist *sg;
struct sym_tcb *tp = &np->target[cp->target];
struct sym_tblmove *data;
if (use_sg > SYM_CONF_MAX_SG) {
- unmap_scsi_data(np, cmd);
+ scsi_dma_unmap(cmd);
return -1;
}
@@ -351,15 +307,6 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd)
int order;
/*
- * Minimal checkings, so that we will not
- * go outside our tables.
- */
- if (sdev->id == np->myaddr) {
- sym_xpt_done2(np, cmd, DID_NO_CONNECT);
- return 0;
- }
-
- /*
* Retrieve the target descriptor.
*/
tp = &np->target[sdev->id];
@@ -433,7 +380,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
*/
switch (dir) {
case DMA_BIDIRECTIONAL:
- printk("%s: got DMA_BIDIRECTIONAL command", sym_name(np));
+ scmd_printk(KERN_INFO, cmd, "got DMA_BIDIRECTIONAL command");
sym_set_cam_status(cmd, DID_ERROR);
goto out_abort;
case DMA_TO_DEVICE:
@@ -542,14 +489,16 @@ static void sym_timer(struct sym_hcb *np)
/*
* PCI BUS error handler.
*/
-void sym_log_bus_error(struct sym_hcb *np)
+void sym_log_bus_error(struct Scsi_Host *shost)
{
- u_short pci_sts;
- pci_read_config_word(np->s.device, PCI_STATUS, &pci_sts);
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ unsigned short pci_sts;
+ pci_read_config_word(pdev, PCI_STATUS, &pci_sts);
if (pci_sts & 0xf900) {
- pci_write_config_word(np->s.device, PCI_STATUS, pci_sts);
- printf("%s: PCI STATUS = 0x%04x\n",
- sym_name(np), pci_sts & 0xf900);
+ pci_write_config_word(pdev, PCI_STATUS, pci_sts);
+ shost_printk(KERN_WARNING, shost,
+ "PCI bus error: status = 0x%04x\n", pci_sts & 0xf900);
}
}
@@ -564,7 +513,7 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd);
int sts = 0;
- cmd->scsi_done = done;
+ cmd->scsi_done = done;
memset(ucp, 0, sizeof(*ucp));
/*
@@ -593,18 +542,23 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
*/
static irqreturn_t sym53c8xx_intr(int irq, void *dev_id)
{
- unsigned long flags;
- struct sym_hcb *np = (struct sym_hcb *)dev_id;
+ struct Scsi_Host *shost = dev_id;
+ struct sym_data *sym_data = shost_priv(shost);
+ irqreturn_t result;
+
+ /* Avoid spinloop trying to handle interrupts on frozen device */
+ if (pci_channel_offline(sym_data->pdev))
+ return IRQ_NONE;
if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("[");
- spin_lock_irqsave(np->s.host->host_lock, flags);
- sym_interrupt(np);
- spin_unlock_irqrestore(np->s.host->host_lock, flags);
+ spin_lock(shost->host_lock);
+ result = sym_interrupt(shost);
+ spin_unlock(shost->host_lock);
if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n");
- return IRQ_HANDLED;
+ return result;
}
/*
@@ -630,59 +584,61 @@ static void sym53c8xx_timer(unsigned long npref)
#define SYM_EH_HOST_RESET 3
/*
- * What we will do regarding the involved SCSI command.
- */
-#define SYM_EH_DO_IGNORE 0
-#define SYM_EH_DO_WAIT 2
-
-/*
- * scsi_done() alias when error recovery is in progress.
- */
-static void sym_eh_done(struct scsi_cmnd *cmd)
-{
- struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
- BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd));
-
- cmd->scsi_done = ucmd->old_done;
-
- if (ucmd->to_do == SYM_EH_DO_WAIT)
- complete(ucmd->eh_done);
-}
-
-/*
* Generic method for our eh processing.
* The 'op' argument tells what we have to do.
*/
static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
{
- struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
- struct Scsi_Host *host = cmd->device->host;
+ struct Scsi_Host *shost = cmd->device->host;
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ struct sym_hcb *np = sym_data->ncb;
SYM_QUEHEAD *qp;
- int to_do = SYM_EH_DO_IGNORE;
+ int cmd_queued = 0;
int sts = -1;
struct completion eh_done;
- dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
+ scmd_printk(KERN_WARNING, cmd, "%s operation started\n", opname);
+
+ /* We may be in an error condition because the PCI bus
+ * went down. In this case, we need to wait until the
+ * PCI bus is reset, the card is reset, and only then
+ * proceed with the scsi error recovery. There's no
+ * point in hurrying; take a leisurely wait.
+ */
+#define WAIT_FOR_PCI_RECOVERY 35
+ if (pci_channel_offline(pdev)) {
+ struct completion *io_reset;
+ int finished_reset = 0;
+ init_completion(&eh_done);
+ spin_lock_irq(shost->host_lock);
+ /* Make sure we didn't race */
+ if (pci_channel_offline(pdev)) {
+ if (!sym_data->io_reset)
+ sym_data->io_reset = &eh_done;
+ io_reset = sym_data->io_reset;
+ } else {
+ finished_reset = 1;
+ }
+ spin_unlock_irq(shost->host_lock);
+ if (!finished_reset)
+ finished_reset = wait_for_completion_timeout(io_reset,
+ WAIT_FOR_PCI_RECOVERY*HZ);
+ if (!finished_reset)
+ return SCSI_FAILED;
+ }
- spin_lock_irq(host->host_lock);
+ spin_lock_irq(shost->host_lock);
/* This one is queued in some place -> to wait for completion */
FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
if (cp->cmd == cmd) {
- to_do = SYM_EH_DO_WAIT;
+ cmd_queued = 1;
break;
}
}
- if (to_do == SYM_EH_DO_WAIT) {
- init_completion(&eh_done);
- ucmd->old_done = cmd->scsi_done;
- ucmd->eh_done = &eh_done;
- wmb();
- cmd->scsi_done = sym_eh_done;
- }
-
/* Try to proceed the operation we have been asked for */
sts = -1;
switch(op) {
@@ -698,7 +654,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
break;
case SYM_EH_HOST_RESET:
sym_reset_scsi_bus(np, 0);
- sym_start_up (np, 1);
+ sym_start_up(shost, 1);
sts = 0;
break;
default:
@@ -706,21 +662,21 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
}
/* On error, restore everything and cross fingers :) */
- if (sts) {
- cmd->scsi_done = ucmd->old_done;
- to_do = SYM_EH_DO_IGNORE;
- }
-
- ucmd->to_do = to_do;
- spin_unlock_irq(host->host_lock);
+ if (sts)
+ cmd_queued = 0;
- if (to_do == SYM_EH_DO_WAIT) {
+ if (cmd_queued) {
+ init_completion(&eh_done);
+ ucmd->eh_done = &eh_done;
+ spin_unlock_irq(shost->host_lock);
if (!wait_for_completion_timeout(&eh_done, 5*HZ)) {
- ucmd->to_do = SYM_EH_DO_IGNORE;
- wmb();
+ ucmd->eh_done = NULL;
sts = -2;
}
+ } else {
+ spin_unlock_irq(shost->host_lock);
}
+
dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
return sts ? SCSI_FAILED : SCSI_SUCCESS;
@@ -775,59 +731,6 @@ static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags)
}
}
-/*
- * Linux select queue depths function
- */
-#define DEF_DEPTH (sym_driver_setup.max_tag)
-#define ALL_TARGETS -2
-#define NO_TARGET -1
-#define ALL_LUNS -2
-#define NO_LUN -1
-
-static int device_queue_depth(struct sym_hcb *np, int target, int lun)
-{
- int c, h, t, u, v;
- char *p = sym_driver_setup.tag_ctrl;
- char *ep;
-
- h = -1;
- t = NO_TARGET;
- u = NO_LUN;
- while ((c = *p++) != 0) {
- v = simple_strtoul(p, &ep, 0);
- switch(c) {
- case '/':
- ++h;
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- case 't':
- if (t != target)
- t = (target == v) ? v : NO_TARGET;
- u = ALL_LUNS;
- break;
- case 'u':
- if (u != lun)
- u = (lun == v) ? v : NO_LUN;
- break;
- case 'q':
- if (h == np->s.unit &&
- (t == ALL_TARGETS || t == target) &&
- (u == ALL_LUNS || u == lun))
- return v;
- break;
- case '-':
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- default:
- break;
- }
- p = ep;
- }
- return DEF_DEPTH;
-}
-
static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
{
struct sym_hcb *np = sym_get_hcb(sdev->host);
@@ -892,21 +795,16 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev)
* Use at least 2.
* Donnot use more than our maximum.
*/
- reqtags = device_queue_depth(np, sdev->id, sdev->lun);
+ reqtags = sym_driver_setup.max_tag;
if (reqtags > tp->usrtags)
reqtags = tp->usrtags;
if (!sdev->tagged_supported)
reqtags = 0;
-#if 1 /* Avoid to locally queue commands for no good reasons */
if (reqtags > SYM_CONF_MAX_TAG)
reqtags = SYM_CONF_MAX_TAG;
- depth_to_use = (reqtags ? reqtags : 2);
-#else
- depth_to_use = (reqtags ? SYM_CONF_MAX_TAG : 2);
-#endif
+ depth_to_use = reqtags ? reqtags : 2;
scsi_adjust_queue_depth(sdev,
- (sdev->tagged_supported ?
- MSG_SIMPLE_TAG : 0),
+ sdev->tagged_supported ? MSG_SIMPLE_TAG : 0,
depth_to_use);
lp->s.scdev_depth = depth_to_use;
sym_tune_dev_queuing(tp, sdev->lun, reqtags);
@@ -1089,8 +987,9 @@ static int is_keyword(char *ptr, int len, char *verb)
* Parse a control command
*/
-static int sym_user_command(struct sym_hcb *np, char *buffer, int length)
+static int sym_user_command(struct Scsi_Host *shost, char *buffer, int length)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
char *ptr = buffer;
int len = length;
struct sym_usrcmd cmd, *uc = &cmd;
@@ -1217,9 +1116,9 @@ printk("sym_user_command: data=%ld\n", uc->data);
else {
unsigned long flags;
- spin_lock_irqsave(np->s.host->host_lock, flags);
- sym_exec_user_command (np, uc);
- spin_unlock_irqrestore(np->s.host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
+ sym_exec_user_command(np, uc);
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
return length;
}
@@ -1275,8 +1174,11 @@ static int copy_info(struct info_str *info, char *fmt, ...)
/*
* Copy formatted information into the input buffer.
*/
-static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
+static int sym_host_info(struct Scsi_Host *shost, char *ptr, off_t offset, int len)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ struct sym_hcb *np = sym_data->ncb;
struct info_str info;
info.buffer = ptr;
@@ -1285,10 +1187,10 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
info.pos = 0;
copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
- "revision id 0x%x\n",
- np->s.chip_name, np->device_id, np->revision_id);
- copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",
- pci_name(np->s.device), IRQ_PRM(np->s.irq));
+ "revision id 0x%x\n", np->s.chip_name,
+ pdev->device, pdev->revision);
+ copy_info(&info, "At PCI address %s, IRQ %u\n",
+ pci_name(pdev), pdev->irq);
copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
(int) (np->minsync_dt ? np->minsync_dt : np->minsync),
np->maxwide ? "Wide" : "Narrow",
@@ -1307,15 +1209,14 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
* - func = 0 means read (returns adapter infos)
* - func = 1 means write (not yet merget from sym53c8xx)
*/
-static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
+static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
char **start, off_t offset, int length, int func)
{
- struct sym_hcb *np = sym_get_hcb(host);
int retv;
if (func) {
#ifdef SYM_LINUX_USER_COMMAND_SUPPORT
- retv = sym_user_command(np, buffer, length);
+ retv = sym_user_command(shost, buffer, length);
#else
retv = -EINVAL;
#endif
@@ -1323,7 +1224,7 @@ static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
if (start)
*start = buffer;
#ifdef SYM_LINUX_USER_INFO_SUPPORT
- retv = sym_host_info(np, buffer, offset, length);
+ retv = sym_host_info(shost, buffer, offset, length);
#else
retv = -EINVAL;
#endif
@@ -1341,8 +1242,8 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
/*
* Free O/S specific resources.
*/
- if (np->s.irq)
- free_irq(np->s.irq, np);
+ if (pdev->irq)
+ free_irq(pdev->irq, np);
if (np->s.ioaddr)
pci_iounmap(pdev, np->s.ioaddr);
if (np->s.ramaddr)
@@ -1356,31 +1257,6 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
}
/*
- * Ask/tell the system about DMA addressing.
- */
-static int sym_setup_bus_dma_mask(struct sym_hcb *np)
-{
-#if SYM_CONF_DMA_ADDRESSING_MODE > 0
-#if SYM_CONF_DMA_ADDRESSING_MODE == 1
-#define DMA_DAC_MASK DMA_40BIT_MASK
-#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-#define DMA_DAC_MASK DMA_64BIT_MASK
-#endif
- if ((np->features & FE_DAC) &&
- !pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) {
- np->use_dac = 1;
- return 0;
- }
-#endif
-
- if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK))
- return 0;
-
- printf_warning("%s: No suitable DMA available\n", sym_name(np));
- return -1;
-}
-
-/*
* Host attach and initialisations.
*
* Allocate host data and ncb structure.
@@ -1392,32 +1268,28 @@ static int sym_setup_bus_dma_mask(struct sym_hcb *np)
static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
int unit, struct sym_device *dev)
{
- struct host_data *host_data;
+ struct sym_data *sym_data;
struct sym_hcb *np = NULL;
- struct Scsi_Host *instance = NULL;
+ struct Scsi_Host *shost;
struct pci_dev *pdev = dev->pdev;
unsigned long flags;
struct sym_fw *fw;
- printk(KERN_INFO
- "sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
- unit, dev->chip.name, dev->chip.revision_id,
- pci_name(pdev), IRQ_PRM(pdev->irq));
+ printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq %u\n",
+ unit, dev->chip.name, pdev->revision, pci_name(pdev),
+ pdev->irq);
/*
* Get the firmware for this chip.
*/
fw = sym_find_firmware(&dev->chip);
if (!fw)
- goto attach_failed;
+ return NULL;
- /*
- * Allocate host_data structure
- */
- instance = scsi_host_alloc(tpnt, sizeof(*host_data));
- if (!instance)
- goto attach_failed;
- host_data = (struct host_data *) instance->hostdata;
+ shost = scsi_host_alloc(tpnt, sizeof(*sym_data));
+ if (!shost)
+ return NULL;
+ sym_data = shost_priv(shost);
/*
* Allocate immediately the host control block,
@@ -1428,22 +1300,19 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
np = __sym_calloc_dma(&pdev->dev, sizeof(*np), "HCB");
if (!np)
goto attach_failed;
- np->s.device = pdev;
np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */
- host_data->ncb = np;
- np->s.host = instance;
+ sym_data->ncb = np;
+ sym_data->pdev = pdev;
+ np->s.host = shost;
- pci_set_drvdata(pdev, np);
+ pci_set_drvdata(pdev, shost);
/*
* Copy some useful infos to the HCB.
*/
np->hcb_ba = vtobus(np);
np->verbose = sym_driver_setup.verbose;
- np->s.device = pdev;
np->s.unit = unit;
- np->device_id = dev->chip.device_id;
- np->revision_id = dev->chip.revision_id;
np->features = dev->chip.features;
np->clock_divn = dev->chip.nr_divisor;
np->maxoffs = dev->chip.offset_max;
@@ -1456,8 +1325,13 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
sprintf(np->s.inst_name, "sym%d", np->s.unit);
- if (sym_setup_bus_dma_mask(np))
+ if ((SYM_CONF_DMA_ADDRESSING_MODE > 0) && (np->features & FE_DAC) &&
+ !pci_set_dma_mask(pdev, DMA_DAC_MASK)) {
+ set_dac(np);
+ } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printf_warning("%s: No suitable DMA available\n", sym_name(np));
goto attach_failed;
+ }
/*
* Try to map the controller chip to
@@ -1466,19 +1340,16 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
np->mmio_ba = (u32)dev->mmio_base;
np->s.ioaddr = dev->s.ioaddr;
np->s.ramaddr = dev->s.ramaddr;
- np->s.io_ws = (np->features & FE_IO256) ? 256 : 128;
/*
* Map on-chip RAM if present and supported.
*/
if (!(np->features & FE_RAM))
dev->ram_base = 0;
- if (dev->ram_base) {
+ if (dev->ram_base)
np->ram_ba = (u32)dev->ram_base;
- np->ram_ws = (np->features & FE_RAM8K) ? 8192 : 4096;
- }
- if (sym_hcb_attach(instance, fw, dev->nvram))
+ if (sym_hcb_attach(shost, fw, dev->nvram))
goto attach_failed;
/*
@@ -1486,25 +1357,25 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* If we synchonize the C code with SCRIPTS on interrupt,
* we do not want to share the INTR line at all.
*/
- if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX, np)) {
- printf_err("%s: request irq %d failure\n",
+ if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX,
+ shost)) {
+ printf_err("%s: request irq %u failure\n",
sym_name(np), pdev->irq);
goto attach_failed;
}
- np->s.irq = pdev->irq;
/*
* After SCSI devices have been opened, we cannot
* reset the bus safely, so we do it here.
*/
- spin_lock_irqsave(instance->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
if (sym_reset_scsi_bus(np, 0))
goto reset_failed;
/*
* Start the SCRIPTS.
*/
- sym_start_up (np, 1);
+ sym_start_up(shost, 1);
/*
* Start the timer daemon
@@ -1519,33 +1390,37 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* Fill Linux host instance structure
* and return success.
*/
- instance->max_channel = 0;
- instance->this_id = np->myaddr;
- instance->max_id = np->maxwide ? 16 : 8;
- instance->max_lun = SYM_CONF_MAX_LUN;
- instance->unique_id = pci_resource_start(pdev, 0);
- instance->cmd_per_lun = SYM_CONF_MAX_TAG;
- instance->can_queue = (SYM_CONF_MAX_START-2);
- instance->sg_tablesize = SYM_CONF_MAX_SG;
- instance->max_cmd_len = 16;
+ shost->max_channel = 0;
+ shost->this_id = np->myaddr;
+ shost->max_id = np->maxwide ? 16 : 8;
+ shost->max_lun = SYM_CONF_MAX_LUN;
+ shost->unique_id = pci_resource_start(pdev, 0);
+ shost->cmd_per_lun = SYM_CONF_MAX_TAG;
+ shost->can_queue = (SYM_CONF_MAX_START-2);
+ shost->sg_tablesize = SYM_CONF_MAX_SG;
+ shost->max_cmd_len = 16;
BUG_ON(sym2_transport_template == NULL);
- instance->transportt = sym2_transport_template;
+ shost->transportt = sym2_transport_template;
+
+ /* 53c896 rev 1 errata: DMA may not cross 16MB boundary */
+ if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 2)
+ shost->dma_boundary = 0xFFFFFF;
- spin_unlock_irqrestore(instance->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
- return instance;
+ return shost;
reset_failed:
printf_err("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, "
"TERMINATION, DEVICE POWER etc.!\n", sym_name(np));
- spin_unlock_irqrestore(instance->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
attach_failed:
- if (!instance)
+ if (!shost)
return NULL;
printf_info("%s: giving up ...\n", sym_name(np));
if (np)
sym_free_resources(np, pdev);
- scsi_host_put(instance);
+ scsi_host_put(shost);
return NULL;
}
@@ -1558,7 +1433,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
static void __devinit sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
{
devp->nvram = nvp;
- devp->device_id = devp->chip.device_id;
nvp->type = 0;
sym_read_nvram(devp, nvp);
@@ -1573,7 +1447,6 @@ static int __devinit sym_check_supported(struct sym_device *device)
{
struct sym_chip *chip;
struct pci_dev *pdev = device->pdev;
- u_char revision;
unsigned long io_port = pci_resource_start(pdev, 0);
int i;
@@ -1593,14 +1466,12 @@ static int __devinit sym_check_supported(struct sym_device *device)
* to our device structure so we can make it match the actual device
* and options.
*/
- pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
- chip = sym_lookup_chip_table(pdev->device, revision);
+ chip = sym_lookup_chip_table(pdev->device, pdev->revision);
if (!chip) {
dev_info(&pdev->dev, "device not supported\n");
return -ENODEV;
}
memcpy(&device->chip, chip, sizeof(device->chip));
- device->chip.revision_id = revision;
return 0;
}
@@ -1641,7 +1512,7 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
* We must ensure the chip will use WRITE AND INVALIDATE.
* The revision number limit is for now arbitrary.
*/
- if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && chip->revision_id < 0x4) {
+ if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 0x4) {
chip->features |= (FE_WRIE | FE_CLSE);
}
@@ -1769,8 +1640,9 @@ static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
* Detach the host.
* We have to free resources and halt the NCR chip.
*/
-static int sym_detach(struct sym_hcb *np, struct pci_dev *pdev)
+static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
printk("%s: detaching ...\n", sym_name(np));
del_timer_sync(&np->s.timer);
@@ -1823,7 +1695,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
{
struct sym_device sym_dev;
struct sym_nvram nvram;
- struct Scsi_Host *instance;
+ struct Scsi_Host *shost;
memset(&sym_dev, 0, sizeof(sym_dev));
memset(&nvram, 0, sizeof(nvram));
@@ -1850,13 +1722,13 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
sym_get_nvram(&sym_dev, &nvram);
- instance = sym_attach(&sym2_template, attach_count, &sym_dev);
- if (!instance)
+ shost = sym_attach(&sym2_template, attach_count, &sym_dev);
+ if (!shost)
goto free;
- if (scsi_add_host(instance, &pdev->dev))
+ if (scsi_add_host(shost, &pdev->dev))
goto detach;
- scsi_scan_host(instance);
+ scsi_scan_host(shost);
attach_count++;
@@ -1874,20 +1746,143 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
static void __devexit sym2_remove(struct pci_dev *pdev)
{
- struct sym_hcb *np = pci_get_drvdata(pdev);
- struct Scsi_Host *host = np->s.host;
-
- scsi_remove_host(host);
- scsi_host_put(host);
-
- sym_detach(np, pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ scsi_remove_host(shost);
+ scsi_host_put(shost);
+ sym_detach(shost, pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
attach_count--;
}
+/**
+ * sym2_io_error_detected() - called when PCI error is detected
+ * @pdev: pointer to PCI device
+ * @state: current state of the PCI slot
+ */
+static pci_ers_result_t sym2_io_error_detected(struct pci_dev *pdev,
+ enum pci_channel_state state)
+{
+ /* If slot is permanently frozen, turn everything off */
+ if (state == pci_channel_io_perm_failure) {
+ sym2_remove(pdev);
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ disable_irq(pdev->irq);
+ pci_disable_device(pdev);
+
+ /* Request that MMIO be enabled, so register dump can be taken. */
+ return PCI_ERS_RESULT_CAN_RECOVER;
+}
+
+/**
+ * sym2_io_slot_dump - Enable MMIO and dump debug registers
+ * @pdev: pointer to PCI device
+ */
+static pci_ers_result_t sym2_io_slot_dump(struct pci_dev *pdev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+
+ sym_dump_registers(shost);
+
+ /* Request a slot reset. */
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * sym2_reset_workarounds - hardware-specific work-arounds
+ *
+ * This routine is similar to sym_set_workarounds(), except
+ * that, at this point, we already know that the device was
+ * succesfully intialized at least once before, and so most
+ * of the steps taken there are un-needed here.
+ */
+static void sym2_reset_workarounds(struct pci_dev *pdev)
+{
+ u_short status_reg;
+ struct sym_chip *chip;
+
+ chip = sym_lookup_chip_table(pdev->device, pdev->revision);
+
+ /* Work around for errant bit in 895A, in a fashion
+ * similar to what is done in sym_set_workarounds().
+ */
+ pci_read_config_word(pdev, PCI_STATUS, &status_reg);
+ if (!(chip->features & FE_66MHZ) && (status_reg & PCI_STATUS_66MHZ)) {
+ status_reg = PCI_STATUS_66MHZ;
+ pci_write_config_word(pdev, PCI_STATUS, status_reg);
+ pci_read_config_word(pdev, PCI_STATUS, &status_reg);
+ }
+}
+
+/**
+ * sym2_io_slot_reset() - called when the pci bus has been reset.
+ * @pdev: pointer to PCI device
+ *
+ * Restart the card from scratch.
+ */
+static pci_ers_result_t sym2_io_slot_reset(struct pci_dev *pdev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct sym_hcb *np = sym_get_hcb(shost);
+
+ printk(KERN_INFO "%s: recovering from a PCI slot reset\n",
+ sym_name(np));
+
+ if (pci_enable_device(pdev)) {
+ printk(KERN_ERR "%s: Unable to enable after PCI reset\n",
+ sym_name(np));
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ pci_set_master(pdev);
+ enable_irq(pdev->irq);
+
+ /* If the chip can do Memory Write Invalidate, enable it */
+ if (np->features & FE_WRIE) {
+ if (pci_set_mwi(pdev))
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ /* Perform work-arounds, analogous to sym_set_workarounds() */
+ sym2_reset_workarounds(pdev);
+
+ /* Perform host reset only on one instance of the card */
+ if (PCI_FUNC(pdev->devfn) == 0) {
+ if (sym_reset_scsi_bus(np, 0)) {
+ printk(KERN_ERR "%s: Unable to reset scsi host\n",
+ sym_name(np));
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ sym_start_up(shost, 1);
+ }
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * sym2_io_resume() - resume normal ops after PCI reset
+ * @pdev: pointer to PCI device
+ *
+ * Called when the error recovery driver tells us that its
+ * OK to resume normal operation. Use completion to allow
+ * halted scsi ops to resume.
+ */
+static void sym2_io_resume(struct pci_dev *pdev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct sym_data *sym_data = shost_priv(shost);
+
+ spin_lock_irq(shost->host_lock);
+ if (sym_data->io_reset)
+ complete_all(sym_data->io_reset);
+ sym_data->io_reset = NULL;
+ spin_unlock_irq(shost->host_lock);
+}
+
static void sym2_get_signalling(struct Scsi_Host *shost)
{
struct sym_hcb *np = sym_get_hcb(shost);
@@ -2050,11 +2045,19 @@ static struct pci_device_id sym2_id_table[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, sym2_id_table);
+static struct pci_error_handlers sym2_err_handler = {
+ .error_detected = sym2_io_error_detected,
+ .mmio_enabled = sym2_io_slot_dump,
+ .slot_reset = sym2_io_slot_reset,
+ .resume = sym2_io_resume,
+};
+
static struct pci_driver sym2_driver = {
.name = NAME53C8XX,
.id_table = sym2_id_table,
.probe = sym2_probe,
.remove = __devexit_p(sym2_remove),
+ .err_handler = &sym2_err_handler,
};
static int __init sym2_init(void)
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index 0f097ba4f71..567fbe0b4f0 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -40,7 +40,9 @@
#ifndef SYM_GLUE_H
#define SYM_GLUE_H
+#include <linux/completion.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/string.h>
@@ -177,14 +179,11 @@ struct sym_shcb {
int unit;
char inst_name[16];
char chip_name[8];
- struct pci_dev *device;
struct Scsi_Host *host;
void __iomem * ioaddr; /* MMIO kernel io address */
void __iomem * ramaddr; /* RAM kernel io address */
- u_short io_ws; /* IO window size */
- int irq; /* IRQ number */
struct timer_list timer; /* Timer handler link header */
u_long lasttime;
@@ -212,20 +211,21 @@ struct sym_device {
} s;
struct sym_chip chip;
struct sym_nvram *nvram;
- u_short device_id;
u_char host_id;
};
/*
* Driver host data structure.
*/
-struct host_data {
+struct sym_data {
struct sym_hcb *ncb;
+ struct completion *io_reset; /* PCI error handling */
+ struct pci_dev *pdev;
};
static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host)
{
- return ((struct host_data *)host->hostdata)->ncb;
+ return ((struct sym_data *)host->hostdata)->ncb;
}
#include "sym_fw.h"
@@ -263,8 +263,8 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
#define sym_print_addr(cmd, arg...) dev_info(&cmd->device->sdev_gendev , ## arg)
void sym_xpt_async_bus_reset(struct sym_hcb *np);
-void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);
-void sym_log_bus_error(struct sym_hcb *np);
+void sym_log_bus_error(struct Scsi_Host *);
+void sym_dump_registers(struct Scsi_Host *);
#endif /* SYM_GLUE_H */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 21cd4c7f528..463f119f20e 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -52,7 +52,7 @@
* Needed function prototypes.
*/
static void sym_int_ma (struct sym_hcb *np);
-static void sym_int_sir (struct sym_hcb *np);
+static void sym_int_sir(struct sym_hcb *);
static struct sym_ccb *sym_alloc_ccb(struct sym_hcb *np);
static struct sym_ccb *sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa);
static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln);
@@ -684,6 +684,8 @@ static void sym_set_bus_mode(struct sym_hcb *np, struct sym_nvram *nvram)
*/
static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
u_char burst_max;
u32 period;
int i;
@@ -778,19 +780,12 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
* 64 bit addressing (895A/896/1010) ?
*/
if (np->features & FE_DAC) {
-#if SYM_CONF_DMA_ADDRESSING_MODE == 0
- np->rv_ccntl1 |= (DDAC);
-#elif SYM_CONF_DMA_ADDRESSING_MODE == 1
- if (!np->use_dac)
- np->rv_ccntl1 |= (DDAC);
- else
- np->rv_ccntl1 |= (XTIMOD | EXTIBMV);
-#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
- if (!np->use_dac)
- np->rv_ccntl1 |= (DDAC);
- else
- np->rv_ccntl1 |= (0 | EXTIBMV);
-#endif
+ if (!use_dac(np))
+ np->rv_ccntl1 |= (DDAC);
+ else if (SYM_CONF_DMA_ADDRESSING_MODE == 1)
+ np->rv_ccntl1 |= (XTIMOD | EXTIBMV);
+ else if (SYM_CONF_DMA_ADDRESSING_MODE == 2)
+ np->rv_ccntl1 |= (0 | EXTIBMV);
}
/*
@@ -804,8 +799,8 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
* In dual channel mode, contention occurs if internal cycles
* are used. Disable internal cycles.
*/
- if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
- np->revision_id < 0x1)
+ if (pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 &&
+ pdev->revision < 0x1)
np->rv_ccntl0 |= DILS;
/*
@@ -828,10 +823,10 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
* this driver. The generic ncr driver that does not use
* LOAD/STORE instructions does not need this work-around.
*/
- if ((np->device_id == PCI_DEVICE_ID_NCR_53C810 &&
- np->revision_id >= 0x10 && np->revision_id <= 0x11) ||
- (np->device_id == PCI_DEVICE_ID_NCR_53C860 &&
- np->revision_id <= 0x1))
+ if ((pdev->device == PCI_DEVICE_ID_NCR_53C810 &&
+ pdev->revision >= 0x10 && pdev->revision <= 0x11) ||
+ (pdev->device == PCI_DEVICE_ID_NCR_53C860 &&
+ pdev->revision <= 0x1))
np->features &= ~(FE_WRIE|FE_ERL|FE_ERMP);
/*
@@ -897,7 +892,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
if ((SYM_SETUP_SCSI_LED ||
(nvram->type == SYM_SYMBIOS_NVRAM ||
(nvram->type == SYM_TEKRAM_NVRAM &&
- np->device_id == PCI_DEVICE_ID_NCR_53C895))) &&
+ pdev->device == PCI_DEVICE_ID_NCR_53C895))) &&
!(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01))
np->features |= FE_LED0;
@@ -1135,8 +1130,9 @@ restart_test:
* First 24 register of the chip:
* r0..rf
*/
-static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
+static void sym_log_hard_error(struct Scsi_Host *shost, u_short sist, u_char dstat)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
u32 dsp;
int script_ofs;
int script_size;
@@ -1180,16 +1176,27 @@ static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
scr_to_cpu((int) *(u32 *)(script_base + script_ofs)));
}
- printf ("%s: regdump:", sym_name(np));
- for (i=0; i<24;i++)
- printf (" %02x", (unsigned)INB_OFF(np, i));
- printf (".\n");
+ printf("%s: regdump:", sym_name(np));
+ for (i = 0; i < 24; i++)
+ printf(" %02x", (unsigned)INB_OFF(np, i));
+ printf(".\n");
/*
* PCI BUS error.
*/
if (dstat & (MDPE|BF))
- sym_log_bus_error(np);
+ sym_log_bus_error(shost);
+}
+
+void sym_dump_registers(struct Scsi_Host *shost)
+{
+ struct sym_hcb *np = sym_get_hcb(shost);
+ u_short sist;
+ u_char dstat;
+
+ sist = INW(np, nc_sist);
+ dstat = INB(np, nc_dstat);
+ sym_log_hard_error(shost, sist, dstat);
}
static struct sym_chip sym_dev_table[] = {
@@ -1312,7 +1319,7 @@ int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s)
{
int i;
- if (!np->use_dac)
+ if (!use_dac(np))
goto weird;
/* Look up existing mappings */
@@ -1519,7 +1526,8 @@ void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
np->squeueput = qidx;
if (DEBUG_FLAGS & DEBUG_QUEUE)
- printf ("%s: queuepos=%d.\n", sym_name (np), np->squeueput);
+ scmd_printk(KERN_DEBUG, cp->cmd, "queuepos=%d\n",
+ np->squeueput);
/*
* Script processor may be waiting for reselect.
@@ -1696,8 +1704,11 @@ static void sym_flush_busy_queue (struct sym_hcb *np, int cam_status)
* 1: SCSI BUS RESET delivered or received.
* 2: SCSI BUS MODE changed.
*/
-void sym_start_up (struct sym_hcb *np, int reason)
+void sym_start_up(struct Scsi_Host *shost, int reason)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct pci_dev *pdev = sym_data->pdev;
+ struct sym_hcb *np = sym_data->ncb;
int i;
u32 phys;
@@ -1746,7 +1757,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
* This also let point to first position the start
* and done queue pointers used from SCRIPTS.
*/
- np->fw_patch(np);
+ np->fw_patch(shost);
/*
* Wakeup all pending jobs.
@@ -1788,7 +1799,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
/*
* For now, disable AIP generation on C1010-66.
*/
- if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)
+ if (pdev->device == PCI_DEVICE_ID_LSI_53C1010_66)
OUTB(np, nc_aipcntl1, DISAIP);
/*
@@ -1798,8 +1809,8 @@ void sym_start_up (struct sym_hcb *np, int reason)
* that from SCRIPTS for each selection/reselection, but
* I just don't want. :)
*/
- if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
- np->revision_id < 1)
+ if (pdev->device == PCI_DEVICE_ID_LSI_53C1010_33 &&
+ pdev->revision < 1)
OUTB(np, nc_stest1, INB(np, nc_stest1) | 0x30);
/*
@@ -1807,9 +1818,9 @@ void sym_start_up (struct sym_hcb *np, int reason)
* Disable overlapped arbitration for some dual function devices,
* regardless revision id (kind of post-chip-design feature. ;-))
*/
- if (np->device_id == PCI_DEVICE_ID_NCR_53C875)
+ if (pdev->device == PCI_DEVICE_ID_NCR_53C875)
OUTB(np, nc_ctest0, (1<<5));
- else if (np->device_id == PCI_DEVICE_ID_NCR_53C896)
+ else if (pdev->device == PCI_DEVICE_ID_NCR_53C896)
np->rv_ccntl0 |= DPR;
/*
@@ -1827,7 +1838,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
* Set up scratch C and DRS IO registers to map the 32 bit
* DMA address range our data structures are located in.
*/
- if (np->use_dac) {
+ if (use_dac(np)) {
np->dmap_bah[0] = 0; /* ??? */
OUTL(np, nc_scrx[0], np->dmap_bah[0]);
OUTL(np, nc_drs, np->dmap_bah[0]);
@@ -1900,7 +1911,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
if (sym_verbose >= 2)
printf("%s: Downloading SCSI SCRIPTS.\n", sym_name(np));
memcpy_toio(np->s.ramaddr, np->scripta0, np->scripta_sz);
- if (np->ram_ws == 8192) {
+ if (np->features & FE_RAM8K) {
memcpy_toio(np->s.ramaddr + 4096, np->scriptb0, np->scriptb_sz);
phys = scr_to_cpu(np->scr_ram_seg);
OUTL(np, nc_mmws, phys);
@@ -2214,8 +2225,9 @@ static void sym_int_udc (struct sym_hcb *np)
* mode to eight bit asynchronous, etc...
* So, just reinitializing all except chip should be enough.
*/
-static void sym_int_sbmc (struct sym_hcb *np)
+static void sym_int_sbmc(struct Scsi_Host *shost)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
u_char scsi_mode = INB(np, nc_stest4) & SMODE;
/*
@@ -2228,7 +2240,7 @@ static void sym_int_sbmc (struct sym_hcb *np)
* Should suspend command processing for a few seconds and
* reinitialize all except the chip.
*/
- sym_start_up (np, 2);
+ sym_start_up(shost, 2);
}
/*
@@ -2756,8 +2768,11 @@ reset_all:
* Use at your own decision and risk.
*/
-void sym_interrupt (struct sym_hcb *np)
+irqreturn_t sym_interrupt(struct Scsi_Host *shost)
{
+ struct sym_data *sym_data = shost_priv(shost);
+ struct sym_hcb *np = sym_data->ncb;
+ struct pci_dev *pdev = sym_data->pdev;
u_char istat, istatc;
u_char dstat;
u_short sist;
@@ -2782,7 +2797,7 @@ void sym_interrupt (struct sym_hcb *np)
}
if (!(istat & (SIP|DIP)))
- return;
+ return (istat & INTF) ? IRQ_HANDLED : IRQ_NONE;
#if 0 /* We should never get this one */
if (istat & CABRT)
@@ -2809,6 +2824,13 @@ void sym_interrupt (struct sym_hcb *np)
dstat |= INB(np, nc_dstat);
istatc = INB(np, nc_istat);
istat |= istatc;
+
+ /* Prevent deadlock waiting on a condition that may
+ * never clear. */
+ if (unlikely(sist == 0xffff && dstat == 0xff)) {
+ if (pci_channel_offline(pdev))
+ return IRQ_NONE;
+ }
} while (istatc & (SIP|DIP));
if (DEBUG_FLAGS & DEBUG_TINY)
@@ -2842,10 +2864,10 @@ void sym_interrupt (struct sym_hcb *np)
!(dstat & (MDPE|BF|ABRT|IID))) {
if (sist & PAR) sym_int_par (np, sist);
else if (sist & MA) sym_int_ma (np);
- else if (dstat & SIR) sym_int_sir (np);
+ else if (dstat & SIR) sym_int_sir(np);
else if (dstat & SSI) OUTONB_STD();
else goto unknown_int;
- return;
+ return IRQ_HANDLED;
}
/*
@@ -2861,8 +2883,8 @@ void sym_interrupt (struct sym_hcb *np)
*/
if (sist & RST) {
printf("%s: SCSI BUS reset detected.\n", sym_name(np));
- sym_start_up (np, 1);
- return;
+ sym_start_up(shost, 1);
+ return IRQ_HANDLED;
}
OUTB(np, nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
@@ -2870,11 +2892,11 @@ void sym_interrupt (struct sym_hcb *np)
if (!(sist & (GEN|HTH|SGE)) &&
!(dstat & (MDPE|BF|ABRT|IID))) {
- if (sist & SBMC) sym_int_sbmc (np);
+ if (sist & SBMC) sym_int_sbmc(shost);
else if (sist & STO) sym_int_sto (np);
else if (sist & UDC) sym_int_udc (np);
else goto unknown_int;
- return;
+ return IRQ_HANDLED;
}
/*
@@ -2884,12 +2906,12 @@ void sym_interrupt (struct sym_hcb *np)
* Reset everything.
*/
- sym_log_hard_error(np, sist, dstat);
+ sym_log_hard_error(shost, sist, dstat);
if ((sist & (GEN|HTH|SGE)) ||
(dstat & (MDPE|BF|ABRT|IID))) {
sym_start_reset(np);
- return;
+ return IRQ_HANDLED;
}
unknown_int:
@@ -2900,6 +2922,7 @@ unknown_int:
printf( "%s: unknown interrupt(s) ignored, "
"ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n",
sym_name(np), istat, dstat, sist);
+ return IRQ_NONE;
}
/*
@@ -3520,7 +3543,8 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* If we sent a BDR, make upper layer aware of that.
*/
if (np->abrt_msg[0] == M_RESET)
- sym_xpt_async_sent_bdr(np, target);
+ starget_printk(KERN_NOTICE, starget,
+ "has been reset\n");
break;
}
@@ -4304,7 +4328,7 @@ static void sym_nego_rejected(struct sym_hcb *np, struct sym_tcb *tp, struct sym
/*
* chip exception handler for programmed interrupts.
*/
-static void sym_int_sir (struct sym_hcb *np)
+static void sym_int_sir(struct sym_hcb *np)
{
u_char num = INB(np, nc_dsps);
u32 dsa = INL(np, nc_dsa);
@@ -4343,31 +4367,30 @@ static void sym_int_sir (struct sym_hcb *np)
return;
/*
* The device didn't go to MSG OUT phase after having
- * been selected with ATN. We donnot want to handle
- * that.
+ * been selected with ATN. We do not want to handle that.
*/
case SIR_SEL_ATN_NO_MSG_OUT:
- printf ("%s:%d: No MSG OUT phase after selection with ATN.\n",
- sym_name (np), target);
+ scmd_printk(KERN_WARNING, cp->cmd,
+ "No MSG OUT phase after selection with ATN\n");
goto out_stuck;
/*
* The device didn't switch to MSG IN phase after
- * having reseleted the initiator.
+ * having reselected the initiator.
*/
case SIR_RESEL_NO_MSG_IN:
- printf ("%s:%d: No MSG IN phase after reselection.\n",
- sym_name (np), target);
+ scmd_printk(KERN_WARNING, cp->cmd,
+ "No MSG IN phase after reselection\n");
goto out_stuck;
/*
* After reselection, the device sent a message that wasn't
* an IDENTIFY.
*/
case SIR_RESEL_NO_IDENTIFY:
- printf ("%s:%d: No IDENTIFY after reselection.\n",
- sym_name (np), target);
+ scmd_printk(KERN_WARNING, cp->cmd,
+ "No IDENTIFY after reselection\n");
goto out_stuck;
/*
- * The device reselected a LUN we donnot know about.
+ * The device reselected a LUN we do not know about.
*/
case SIR_RESEL_BAD_LUN:
np->msgout[0] = M_RESET;
@@ -4380,8 +4403,7 @@ static void sym_int_sir (struct sym_hcb *np)
np->msgout[0] = M_ABORT;
goto out;
/*
- * The device reselected for a tagged nexus that we donnot
- * have.
+ * The device reselected for a tagged nexus that we do not have.
*/
case SIR_RESEL_BAD_I_T_L_Q:
np->msgout[0] = M_ABORT_TAG;
@@ -4393,8 +4415,8 @@ static void sym_int_sir (struct sym_hcb *np)
case SIR_RESEL_ABORTED:
np->lastmsg = np->msgout[0];
np->msgout[0] = M_NOOP;
- printf ("%s:%d: message %x sent on bad reselection.\n",
- sym_name (np), target, np->lastmsg);
+ scmd_printk(KERN_WARNING, cp->cmd,
+ "message %x sent on bad reselection\n", np->lastmsg);
goto out;
/*
* The SCRIPTS let us know that a message has been
@@ -5578,16 +5600,13 @@ int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram
np->scriptz_ba = vtobus(np->scriptz0);
if (np->ram_ba) {
- np->scripta_ba = np->ram_ba;
+ np->scripta_ba = np->ram_ba;
if (np->features & FE_RAM8K) {
- np->ram_ws = 8192;
np->scriptb_ba = np->scripta_ba + 4096;
#if 0 /* May get useful for 64 BIT PCI addressing */
np->scr_ram_seg = cpu_to_scr(np->scripta_ba >> 32);
#endif
}
- else
- np->ram_ws = 4096;
}
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 79ab6a17703..ad078805e62 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -883,10 +883,7 @@ struct sym_hcb {
* Physical bus addresses of the chip.
*/
u32 mmio_ba; /* MMIO 32 bit BUS address */
- int mmio_ws; /* MMIO Window size */
-
u32 ram_ba; /* RAM 32 bit BUS address */
- int ram_ws; /* RAM window size */
/*
* SCRIPTS virtual and physical bus addresses.
@@ -912,14 +909,12 @@ struct sym_hcb {
struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */
struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */
void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw);
- void (*fw_patch)(struct sym_hcb *np);
+ void (*fw_patch)(struct Scsi_Host *);
char *fw_name;
/*
* General controller parameters and configuration.
*/
- u_short device_id; /* PCI device id */
- u_char revision_id; /* PCI device revision id */
u_int features; /* Chip features map */
u_char myaddr; /* SCSI id of the adapter */
u_char maxburst; /* log base 2 of dwords burst */
@@ -1031,6 +1026,14 @@ struct sym_hcb {
#endif
};
+#if SYM_CONF_DMA_ADDRESSING_MODE == 0
+#define use_dac(np) 0
+#define set_dac(np) do { } while (0)
+#else
+#define use_dac(np) (np)->use_dac
+#define set_dac(np) (np)->use_dac = 1
+#endif
+
#define HCB_BA(np, lbl) (np->hcb_ba + offsetof(struct sym_hcb, lbl))
@@ -1052,8 +1055,8 @@ void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
#else
void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
#endif
-void sym_start_up(struct sym_hcb *np, int reason);
-void sym_interrupt(struct sym_hcb *np);
+void sym_start_up(struct Scsi_Host *, int reason);
+irqreturn_t sym_interrupt(struct Scsi_Host *);
int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order);
void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp);
@@ -1073,18 +1076,21 @@ int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram
*/
#if SYM_CONF_DMA_ADDRESSING_MODE == 0
+#define DMA_DAC_MASK DMA_32BIT_MASK
#define sym_build_sge(np, data, badd, len) \
do { \
(data)->addr = cpu_to_scr(badd); \
(data)->size = cpu_to_scr(len); \
} while (0)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 1
+#define DMA_DAC_MASK DMA_40BIT_MASK
#define sym_build_sge(np, data, badd, len) \
do { \
(data)->addr = cpu_to_scr(badd); \
(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \
} while (0)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
+#define DMA_DAC_MASK DMA_64BIT_MASK
int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
static __inline void
sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index 15d69298ab6..5662fbb3ff6 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -696,7 +696,7 @@ static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram)
u_short csum;
int x;
- switch (np->device_id) {
+ switch (np->pdev->device) {
case PCI_DEVICE_ID_NCR_53C885:
case PCI_DEVICE_ID_NCR_53C895:
case PCI_DEVICE_ID_NCR_53C896:
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 37bddc1802d..81db48f07ca 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -343,11 +343,12 @@ config IBMASR
module will be called ibmasr.
config WAFER_WDT
- tristate "ICP Wafer 5823 Single Board Computer Watchdog"
+ tristate "ICP Single Board Computer Watchdog Timer"
depends on X86
help
- This is a driver for the hardware watchdog on the ICP Wafer 5823
- Single Board Computer (and probably other similar models).
+ This is a driver for the hardware watchdog on the ICP Single
+ Board Computer. This driver is working on (at least) the following
+ IPC SBC's: Wafer 5823, Rocky 4783, Rocky 3703 and Rocky 3782.
To compile this driver as a module, choose M here: the
module will be called wafer5823wdt.
@@ -609,6 +610,12 @@ config WDT_RM9K_GPI
To compile this driver as a module, choose M here: the
module will be called rm9k_wdt.
+config AR7_WDT
+ tristate "TI AR7 Watchdog Timer"
+ depends on AR7
+ help
+ Hardware driver for the TI AR7 Watchdog Timer.
+
# PARISC Architecture
# POWERPC Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 389f8b14ccc..7d9e5734f8b 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -90,6 +90,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
obj-$(CONFIG_INDYDOG) += indydog.o
obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
+obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
# PARISC Architecture
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
new file mode 100644
index 00000000000..cdaab8c3d3d
--- /dev/null
+++ b/drivers/watchdog/ar7_wdt.c
@@ -0,0 +1,349 @@
+/*
+ * drivers/watchdog/ar7_wdt.c
+ *
+ * Copyright (C) 2007 Nicolas Thill <nico@openwrt.org>
+ * Copyright (c) 2005 Enrik Berkhan <Enrik.Berkhan@akk.org>
+ *
+ * Some code taken from:
+ * National Semiconductor SCx200 Watchdog support
+ * Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <asm/addrspace.h>
+#include <asm/ar7/ar7.h>
+
+#define DRVNAME "ar7_wdt"
+#define LONGNAME "TI AR7 Watchdog Timer"
+
+MODULE_AUTHOR("Nicolas Thill <nico@openwrt.org>");
+MODULE_DESCRIPTION(LONGNAME);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+static int margin = 60;
+module_param(margin, int, 0);
+MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
+
+#define READ_REG(x) readl((void __iomem *)&(x))
+#define WRITE_REG(x, v) writel((v), (void __iomem *)&(x))
+
+struct ar7_wdt {
+ u32 kick_lock;
+ u32 kick;
+ u32 change_lock;
+ u32 change;
+ u32 disable_lock;
+ u32 disable;
+ u32 prescale_lock;
+ u32 prescale;
+};
+
+static struct semaphore open_semaphore;
+static unsigned expect_close;
+
+/* XXX currently fixed, allows max margin ~68.72 secs */
+#define prescale_value 0xffff
+
+/* Offset of the WDT registers */
+static unsigned long ar7_regs_wdt;
+/* Pointer to the remapped WDT IO space */
+static struct ar7_wdt *ar7_wdt;
+static void ar7_wdt_get_regs(void)
+{
+ u16 chip_id = ar7_chip_id();
+ switch (chip_id) {
+ case AR7_CHIP_7100:
+ case AR7_CHIP_7200:
+ ar7_regs_wdt = AR7_REGS_WDT;
+ break;
+ default:
+ ar7_regs_wdt = UR8_REGS_WDT;
+ break;
+ }
+}
+
+
+static void ar7_wdt_kick(u32 value)
+{
+ WRITE_REG(ar7_wdt->kick_lock, 0x5555);
+ if ((READ_REG(ar7_wdt->kick_lock) & 3) == 1) {
+ WRITE_REG(ar7_wdt->kick_lock, 0xaaaa);
+ if ((READ_REG(ar7_wdt->kick_lock) & 3) == 3) {
+ WRITE_REG(ar7_wdt->kick, value);
+ return;
+ }
+ }
+ printk(KERN_ERR DRVNAME ": failed to unlock WDT kick reg\n");
+}
+
+static void ar7_wdt_prescale(u32 value)
+{
+ WRITE_REG(ar7_wdt->prescale_lock, 0x5a5a);
+ if ((READ_REG(ar7_wdt->prescale_lock) & 3) == 1) {
+ WRITE_REG(ar7_wdt->prescale_lock, 0xa5a5);
+ if ((READ_REG(ar7_wdt->prescale_lock) & 3) == 3) {
+ WRITE_REG(ar7_wdt->prescale, value);
+ return;
+ }
+ }
+ printk(KERN_ERR DRVNAME ": failed to unlock WDT prescale reg\n");
+}
+
+static void ar7_wdt_change(u32 value)
+{
+ WRITE_REG(ar7_wdt->change_lock, 0x6666);
+ if ((READ_REG(ar7_wdt->change_lock) & 3) == 1) {
+ WRITE_REG(ar7_wdt->change_lock, 0xbbbb);
+ if ((READ_REG(ar7_wdt->change_lock) & 3) == 3) {
+ WRITE_REG(ar7_wdt->change, value);
+ return;
+ }
+ }
+ printk(KERN_ERR DRVNAME ": failed to unlock WDT change reg\n");
+}
+
+static void ar7_wdt_disable(u32 value)
+{
+ WRITE_REG(ar7_wdt->disable_lock, 0x7777);
+ if ((READ_REG(ar7_wdt->disable_lock) & 3) == 1) {
+ WRITE_REG(ar7_wdt->disable_lock, 0xcccc);
+ if ((READ_REG(ar7_wdt->disable_lock) & 3) == 2) {
+ WRITE_REG(ar7_wdt->disable_lock, 0xdddd);
+ if ((READ_REG(ar7_wdt->disable_lock) & 3) == 3) {
+ WRITE_REG(ar7_wdt->disable, value);
+ return;
+ }
+ }
+ }
+ printk(KERN_ERR DRVNAME ": failed to unlock WDT disable reg\n");
+}
+
+static void ar7_wdt_update_margin(int new_margin)
+{
+ u32 change;
+
+ change = new_margin * (ar7_vbus_freq() / prescale_value);
+ if (change < 1) change = 1;
+ if (change > 0xffff) change = 0xffff;
+ ar7_wdt_change(change);
+ margin = change * prescale_value / ar7_vbus_freq();
+ printk(KERN_INFO DRVNAME
+ ": timer margin %d seconds (prescale %d, change %d, freq %d)\n",
+ margin, prescale_value, change, ar7_vbus_freq());
+}
+
+static void ar7_wdt_enable_wdt(void)
+{
+ printk(KERN_DEBUG DRVNAME ": enabling watchdog timer\n");
+ ar7_wdt_disable(1);
+ ar7_wdt_kick(1);
+}
+
+static void ar7_wdt_disable_wdt(void)
+{
+ printk(KERN_DEBUG DRVNAME ": disabling watchdog timer\n");
+ ar7_wdt_disable(0);
+}
+
+static int ar7_wdt_open(struct inode *inode, struct file *file)
+{
+ /* only allow one at a time */
+ if (down_trylock(&open_semaphore))
+ return -EBUSY;
+ ar7_wdt_enable_wdt();
+ expect_close = 0;
+
+ return nonseekable_open(inode, file);
+}
+
+static int ar7_wdt_release(struct inode *inode, struct file *file)
+{
+ if (!expect_close)
+ printk(KERN_WARNING DRVNAME
+ ": watchdog device closed unexpectedly,"
+ "will not disable the watchdog timer\n");
+ else if (!nowayout)
+ ar7_wdt_disable_wdt();
+
+ up(&open_semaphore);
+
+ return 0;
+}
+
+static int ar7_wdt_notify_sys(struct notifier_block *this,
+ unsigned long code, void *unused)
+{
+ if (code == SYS_HALT || code == SYS_POWER_OFF)
+ if (!nowayout)
+ ar7_wdt_disable_wdt();
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ar7_wdt_notifier = {
+ .notifier_call = ar7_wdt_notify_sys
+};
+
+static ssize_t ar7_wdt_write(struct file *file, const char *data,
+ size_t len, loff_t *ppos)
+{
+ /* check for a magic close character */
+ if (len) {
+ size_t i;
+
+ ar7_wdt_kick(1);
+
+ expect_close = 0;
+ for (i = 0; i < len; ++i) {
+ char c;
+ if (get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 1;
+ }
+
+ }
+ return len;
+}
+
+static int ar7_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ static struct watchdog_info ident = {
+ .identity = LONGNAME,
+ .firmware_version = 1,
+ .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING),
+ };
+ int new_margin;
+
+ switch (cmd) {
+ default:
+ return -ENOTTY;
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user((struct watchdog_info *)arg, &ident,
+ sizeof(ident)))
+ return -EFAULT;
+ return 0;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ if (put_user(0, (int *)arg))
+ return -EFAULT;
+ return 0;
+ case WDIOC_KEEPALIVE:
+ ar7_wdt_kick(1);
+ return 0;
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_margin, (int *)arg))
+ return -EFAULT;
+ if (new_margin < 1)
+ return -EINVAL;
+
+ ar7_wdt_update_margin(new_margin);
+ ar7_wdt_kick(1);
+
+ case WDIOC_GETTIMEOUT:
+ if (put_user(margin, (int *)arg))
+ return -EFAULT;
+ return 0;
+ }
+}
+
+static struct file_operations ar7_wdt_fops = {
+ .owner = THIS_MODULE,
+ .write = ar7_wdt_write,
+ .ioctl = ar7_wdt_ioctl,
+ .open = ar7_wdt_open,
+ .release = ar7_wdt_release,
+};
+
+static struct miscdevice ar7_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &ar7_wdt_fops,
+};
+
+static int __init ar7_wdt_init(void)
+{
+ int rc;
+
+ ar7_wdt_get_regs();
+
+ if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt),
+ LONGNAME)) {
+ printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
+ return -EBUSY;
+ }
+
+ ar7_wdt = (struct ar7_wdt *)
+ ioremap(ar7_regs_wdt, sizeof(struct ar7_wdt));
+
+ ar7_wdt_disable_wdt();
+ ar7_wdt_prescale(prescale_value);
+ ar7_wdt_update_margin(margin);
+
+ sema_init(&open_semaphore, 1);
+
+ rc = register_reboot_notifier(&ar7_wdt_notifier);
+ if (rc) {
+ printk(KERN_ERR DRVNAME
+ ": unable to register reboot notifier\n");
+ goto out_alloc;
+ }
+
+ rc = misc_register(&ar7_wdt_miscdev);
+ if (rc) {
+ printk(KERN_ERR DRVNAME ": unable to register misc device\n");
+ goto out_register;
+ }
+ goto out;
+
+out_register:
+ unregister_reboot_notifier(&ar7_wdt_notifier);
+out_alloc:
+ iounmap(ar7_wdt);
+ release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt));
+out:
+ return rc;
+}
+
+static void __exit ar7_wdt_cleanup(void)
+{
+ misc_deregister(&ar7_wdt_miscdev);
+ unregister_reboot_notifier(&ar7_wdt_notifier);
+ iounmap(ar7_wdt);
+ release_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt));
+}
+
+module_init(ar7_wdt_init);
+module_exit(ar7_wdt_cleanup);