summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/bay.c2
-rw-r--r--drivers/ata/ahci.c2
-rw-r--r--drivers/ata/sata_svw.c6
-rw-r--r--drivers/char/watchdog/machzwd.c2
-rw-r--r--drivers/crypto/geode-aes.c2
-rw-r--r--drivers/hwmon/ams/ams-input.c2
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c4
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c2
-rw-r--r--drivers/kvm/kvm_main.c63
-rw-r--r--drivers/kvm/mmu.c2
-rw-r--r--drivers/kvm/svm.c8
-rw-r--r--drivers/kvm/vmx.c2
-rw-r--r--drivers/macintosh/rack-meter.c6
-rw-r--r--drivers/media/common/ir-keymaps.c1
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c2
-rw-r--r--drivers/misc/Kconfig2
-rw-r--r--drivers/misc/lkdtm.c4
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/net/3c503.c3
-rw-r--r--drivers/net/Kconfig11
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/ac3200.c3
-rw-r--r--drivers/net/atl1/Makefile2
-rw-r--r--drivers/net/atl1/atl1.h283
-rw-r--r--drivers/net/atl1/atl1_ethtool.c508
-rw-r--r--drivers/net/atl1/atl1_hw.c718
-rw-r--r--drivers/net/atl1/atl1_hw.h951
-rw-r--r--drivers/net/atl1/atl1_main.c2468
-rw-r--r--drivers/net/atl1/atl1_param.c206
-rw-r--r--drivers/net/bonding/bond_alb.c4
-rw-r--r--drivers/net/bonding/bond_main.c4
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c86
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c4
-rw-r--r--drivers/net/e2100.c3
-rw-r--r--drivers/net/es3210.c2
-rw-r--r--drivers/net/macsonic.c1
-rw-r--r--drivers/net/mv643xx_eth.c1
-rw-r--r--drivers/net/r8169.c4
-rw-r--r--drivers/net/s2io.c2
-rw-r--r--drivers/net/s2io.h6
-rw-r--r--drivers/net/slip.c5
-rw-r--r--drivers/net/smc-mca.c3
-rw-r--r--drivers/net/smc-ultra.c3
-rw-r--r--drivers/net/smc-ultra32.c3
-rw-r--r--drivers/net/spider_net.c2
-rw-r--r--drivers/net/tg3.c2
-rw-r--r--drivers/net/ucc_geth.c79
-rw-r--r--drivers/net/ucc_geth_phy.c2
-rw-r--r--drivers/net/wan/pc300too.c16
-rw-r--r--drivers/net/wd.c2
-rw-r--r--drivers/pcmcia/m32r_pcc.c2
-rw-r--r--drivers/rtc/rtc-dev.c2
-rw-r--r--drivers/s390/char/monreader.c218
-rw-r--r--drivers/s390/char/vmlogrdr.c279
-rw-r--r--drivers/s390/net/Kconfig7
-rw-r--r--drivers/s390/net/Makefile1
-rw-r--r--drivers/s390/net/iucv.c2540
-rw-r--r--drivers/s390/net/iucv.h849
-rw-r--r--drivers/s390/net/netiucv.c1314
-rw-r--r--drivers/s390/net/smsgiucv.c147
-rw-r--r--drivers/scsi/iscsi_tcp.c2
-rw-r--r--drivers/scsi/libiscsi.c40
-rw-r--r--drivers/scsi/osst.c8
-rw-r--r--drivers/scsi/osst.h68
-rw-r--r--drivers/serial/uartlite.c6
-rw-r--r--drivers/usb/host/ehci-ps3.c2
-rw-r--r--drivers/usb/host/ehci.h12
-rw-r--r--drivers/usb/host/ohci-ps3.c2
-rw-r--r--drivers/usb/host/ohci.h12
-rw-r--r--drivers/usb/net/gl620a.c26
-rw-r--r--drivers/usb/serial/cp2101.c8
71 files changed, 6341 insertions, 4706 deletions
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
index 667fa1dfa1a3..91082ce6f5d1 100644
--- a/drivers/acpi/bay.c
+++ b/drivers/acpi/bay.c
@@ -296,7 +296,7 @@ static int bay_add(acpi_handle handle, int id)
/*
* Initialize bay device structure
*/
- new_bay = kzalloc(GFP_ATOMIC, sizeof(*new_bay));
+ new_bay = kzalloc(sizeof(*new_bay), GFP_ATOMIC);
INIT_LIST_HEAD(&new_bay->list);
new_bay->handle = handle;
new_bay->name = (char *)nbuffer.pointer;
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 48616c6fee9d..e2796fb40eb7 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1173,7 +1173,7 @@ static void ahci_host_intr(struct ata_port *ap)
* dangerous, we need to know more about them. Print
* more of it.
*/
- const u32 *f = pp->rx_fis + RX_FIS_SDB;
+ const __le32 *f = pp->rx_fis + RX_FIS_SDB;
ata_port_printk(ap, KERN_INFO, "Spurious SDB FIS during NCQ "
"issue=0x%x SAct=0x%x FIS=%08x:%08x%s\n",
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 46d8a94669b4..5f4e82ade6cd 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -116,7 +116,7 @@ static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
- return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -125,7 +125,7 @@ static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
{
if (sc_reg > SCR_CONTROL)
return;
- writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -262,7 +262,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
static u8 k2_stat_check_status(struct ata_port *ap)
{
- return readl((void *) ap->ioaddr.status_addr);
+ return readl((void __iomem *) ap->ioaddr.status_addr);
}
#ifdef CONFIG_PPC_OF
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
index 276577d08fba..4d730fdbd528 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/char/watchdog/machzwd.c
@@ -325,7 +325,7 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return put_user(0, p);
case WDIOC_KEEPALIVE:
- zf_ping(0);
+ zf_ping(NULL);
break;
default:
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index 43a68398656f..31ea405f2eeb 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -457,7 +457,7 @@ static struct pci_driver geode_aes_driver = {
static int __init
geode_aes_init(void)
{
- return pci_module_init(&geode_aes_driver);
+ return pci_register_driver(&geode_aes_driver);
}
static void __exit
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c
index f126aa485134..18210164e307 100644
--- a/drivers/hwmon/ams/ams-input.c
+++ b/drivers/hwmon/ams/ams-input.c
@@ -153,7 +153,7 @@ int ams_input_init(void)
}
/* Call with ams_info.lock held! */
-void ams_input_exit()
+void ams_input_exit(void)
{
ams_input_disable();
device_remove_file(&ams_info.of_dev->dev, &dev_attr_joystick);
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 0a7d1ab60e6d..89e37283c836 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -567,7 +567,7 @@ void iser_rcv_completion(struct iser_desc *rx_desc,
opcode = hdr->opcode & ISCSI_OPCODE_MASK;
if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
- itt = hdr->itt & ISCSI_ITT_MASK; /* mask out cid and age bits */
+ itt = get_itt(hdr->itt); /* mask out cid and age bits */
if (!(itt < session->cmds_max))
iser_err("itt can't be matched to task!!!"
"conn %p opcode %d cmds_max %d itt %d\n",
@@ -625,7 +625,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
/* this arithmetic is legal by libiscsi dd_data allocation */
mtask = (void *) ((long)(void *)tx_desc -
sizeof(struct iscsi_mgmt_task));
- if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+ if (mtask->hdr->itt == RESERVED_ITT) {
struct iscsi_session *session = conn->session;
spin_lock(&conn->session->lock);
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 4358a0a78eaa..c7db4032ef02 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -83,7 +83,7 @@
struct ucb1400 {
- ac97_t *ac97;
+ struct snd_ac97 *ac97;
struct input_dev *ts_idev;
int irq;
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index b10972ed0c9f..099f0afd394d 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -62,7 +62,7 @@ static struct kvm_stats_debugfs_item {
{ "halt_exits", &kvm_stat.halt_exits },
{ "request_irq", &kvm_stat.request_irq_exits },
{ "irq_exits", &kvm_stat.irq_exits },
- { 0, 0 }
+ { NULL, NULL }
};
static struct dentry *debugfs_dir;
@@ -205,7 +205,7 @@ static struct kvm_vcpu *vcpu_load(struct kvm *kvm, int vcpu_slot)
mutex_lock(&vcpu->mutex);
if (unlikely(!vcpu->vmcs)) {
mutex_unlock(&vcpu->mutex);
- return 0;
+ return NULL;
}
return kvm_arch_ops->vcpu_load(vcpu);
}
@@ -257,9 +257,9 @@ static void kvm_free_physmem_slot(struct kvm_memory_slot *free,
if (!dont || free->dirty_bitmap != dont->dirty_bitmap)
vfree(free->dirty_bitmap);
- free->phys_mem = 0;
+ free->phys_mem = NULL;
free->npages = 0;
- free->dirty_bitmap = 0;
+ free->dirty_bitmap = NULL;
}
static void kvm_free_physmem(struct kvm *kvm)
@@ -267,7 +267,7 @@ static void kvm_free_physmem(struct kvm *kvm)
int i;
for (i = 0; i < kvm->nmemslots; ++i)
- kvm_free_physmem_slot(&kvm->memslots[i], 0);
+ kvm_free_physmem_slot(&kvm->memslots[i], NULL);
}
static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
@@ -640,11 +640,11 @@ raced:
/* Deallocate if slot is being removed */
if (!npages)
- new.phys_mem = 0;
+ new.phys_mem = NULL;
/* Free page dirty bitmap if unneeded */
if (!(new.flags & KVM_MEM_LOG_DIRTY_PAGES))
- new.dirty_bitmap = 0;
+ new.dirty_bitmap = NULL;
r = -ENOMEM;
@@ -799,14 +799,14 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
&& gfn < memslot->base_gfn + memslot->npages)
return memslot;
}
- return 0;
+ return NULL;
}
EXPORT_SYMBOL_GPL(gfn_to_memslot);
void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
{
int i;
- struct kvm_memory_slot *memslot = 0;
+ struct kvm_memory_slot *memslot = NULL;
unsigned long rel_gfn;
for (i = 0; i < kvm->nmemslots; ++i) {
@@ -1778,6 +1778,7 @@ static long kvm_dev_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
struct kvm *kvm = filp->private_data;
+ void __user *argp = (void __user *)arg;
int r = -EINVAL;
switch (ioctl) {
@@ -1794,12 +1795,12 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_run kvm_run;
r = -EFAULT;
- if (copy_from_user(&kvm_run, (void *)arg, sizeof kvm_run))
+ if (copy_from_user(&kvm_run, argp, sizeof kvm_run))
goto out;
r = kvm_dev_ioctl_run(kvm, &kvm_run);
if (r < 0 && r != -EINTR)
goto out;
- if (copy_to_user((void *)arg, &kvm_run, sizeof kvm_run)) {
+ if (copy_to_user(argp, &kvm_run, sizeof kvm_run)) {
r = -EFAULT;
goto out;
}
@@ -1809,13 +1810,13 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_regs kvm_regs;
r = -EFAULT;
- if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+ if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
goto out;
r = kvm_dev_ioctl_get_regs(kvm, &kvm_regs);
if (r)
goto out;
r = -EFAULT;
- if (copy_to_user((void *)arg, &kvm_regs, sizeof kvm_regs))
+ if (copy_to_user(argp, &kvm_regs, sizeof kvm_regs))
goto out;
r = 0;
break;
@@ -1824,7 +1825,7 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_regs kvm_regs;
r = -EFAULT;
- if (copy_from_user(&kvm_regs, (void *)arg, sizeof kvm_regs))
+ if (copy_from_user(&kvm_regs, argp, sizeof kvm_regs))
goto out;
r = kvm_dev_ioctl_set_regs(kvm, &kvm_regs);
if (r)
@@ -1836,13 +1837,13 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_sregs kvm_sregs;
r = -EFAULT;
- if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+ if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs))
goto out;
r = kvm_dev_ioctl_get_sregs(kvm, &kvm_sregs);
if (r)
goto out;
r = -EFAULT;
- if (copy_to_user((void *)arg, &kvm_sregs, sizeof kvm_sregs))
+ if (copy_to_user(argp, &kvm_sregs, sizeof kvm_sregs))
goto out;
r = 0;
break;
@@ -1851,7 +1852,7 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_sregs kvm_sregs;
r = -EFAULT;
- if (copy_from_user(&kvm_sregs, (void *)arg, sizeof kvm_sregs))
+ if (copy_from_user(&kvm_sregs, argp, sizeof kvm_sregs))
goto out;
r = kvm_dev_ioctl_set_sregs(kvm, &kvm_sregs);
if (r)
@@ -1863,13 +1864,13 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_translation tr;
r = -EFAULT;
- if (copy_from_user(&tr, (void *)arg, sizeof tr))
+ if (copy_from_user(&tr, argp, sizeof tr))
goto out;
r = kvm_dev_ioctl_translate(kvm, &tr);
if (r)
goto out;
r = -EFAULT;
- if (copy_to_user((void *)arg, &tr, sizeof tr))
+ if (copy_to_user(argp, &tr, sizeof tr))
goto out;
r = 0;
break;
@@ -1878,7 +1879,7 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_interrupt irq;
r = -EFAULT;
- if (copy_from_user(&irq, (void *)arg, sizeof irq))
+ if (copy_from_user(&irq, argp, sizeof irq))
goto out;
r = kvm_dev_ioctl_interrupt(kvm, &irq);
if (r)
@@ -1890,7 +1891,7 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_debug_guest dbg;
r = -EFAULT;
- if (copy_from_user(&dbg, (void *)arg, sizeof dbg))
+ if (copy_from_user(&dbg, argp, sizeof dbg))
goto out;
r = kvm_dev_ioctl_debug_guest(kvm, &dbg);
if (r)
@@ -1902,7 +1903,7 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_memory_region kvm_mem;
r = -EFAULT;
- if (copy_from_user(&kvm_mem, (void *)arg, sizeof kvm_mem))
+ if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
goto out;
r = kvm_dev_ioctl_set_memory_region(kvm, &kvm_mem);
if (r)
@@ -1913,7 +1914,7 @@ static long kvm_dev_ioctl(struct file *filp,
struct kvm_dirty_log log;
r = -EFAULT;
- if (copy_from_user(&log, (void *)arg, sizeof log))
+ if (copy_from_user(&log, argp, sizeof log))
goto out;
r = kvm_dev_ioctl_get_dirty_log(kvm, &log);
if (r)
@@ -1921,13 +1922,13 @@ static long kvm_dev_ioctl(struct file *filp,
break;
}
case KVM_GET_MSRS:
- r = msr_io(kvm, (void __user *)arg, get_msr, 1);
+ r = msr_io(kvm, argp, get_msr, 1);
break;
case KVM_SET_MSRS:
- r = msr_io(kvm, (void __user *)arg, do_set_msr, 0);
+ r = msr_io(kvm, argp, do_set_msr, 0);
break;
case KVM_GET_MSR_INDEX_LIST: {
- struct kvm_msr_list __user *user_msr_list = (void __user *)arg;
+ struct kvm_msr_list __user *user_msr_list = argp;
struct kvm_msr_list msr_list;
unsigned n;
@@ -2014,7 +2015,7 @@ static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
* in vmx root mode.
*/
printk(KERN_INFO "kvm: exiting hardware virtualization\n");
- on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+ on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
}
return NOTIFY_OK;
}
@@ -2028,7 +2029,7 @@ static __init void kvm_init_debug(void)
{
struct kvm_stats_debugfs_item *p;
- debugfs_dir = debugfs_create_dir("kvm", 0);
+ debugfs_dir = debugfs_create_dir("kvm", NULL);
for (p = debugfs_entries; p->name; ++p)
p->dentry = debugfs_create_u32(p->name, 0444, debugfs_dir,
p->data);
@@ -2069,7 +2070,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
if (r < 0)
return r;
- on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1);
+ on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
register_reboot_notifier(&kvm_reboot_notifier);
kvm_chardev_ops.owner = module;
@@ -2084,7 +2085,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
out_free:
unregister_reboot_notifier(&kvm_reboot_notifier);
- on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+ on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
kvm_arch_ops->hardware_unsetup();
return r;
}
@@ -2094,7 +2095,7 @@ void kvm_exit_arch(void)
misc_deregister(&kvm_dev);
unregister_reboot_notifier(&kvm_reboot_notifier);
- on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+ on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
kvm_arch_ops->hardware_unsetup();
kvm_arch_ops = NULL;
}
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 22c426cd8cb2..be793770f31b 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -333,7 +333,7 @@ static void rmap_desc_remove_entry(struct kvm_vcpu *vcpu,
for (j = RMAP_EXT - 1; !desc->shadow_ptes[j] && j > i; --j)
;
desc->shadow_ptes[i] = desc->shadow_ptes[j];
- desc->shadow_ptes[j] = 0;
+ desc->shadow_ptes[j] = NULL;
if (j != 0)
return;
if (!prev_desc && !desc->more)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index c79df79307ed..85f61dd1e936 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -274,7 +274,7 @@ static void svm_hardware_disable(void *garbage)
wrmsrl(MSR_VM_HSAVE_PA, 0);
rdmsrl(MSR_EFER, efer);
wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
- per_cpu(svm_data, raw_smp_processor_id()) = 0;
+ per_cpu(svm_data, raw_smp_processor_id()) = NULL;
__free_page(svm_data->save_area);
kfree(svm_data);
}
@@ -642,7 +642,7 @@ static struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg)
case VCPU_SREG_LDTR: return &save->ldtr;
}
BUG();
- return 0;
+ return NULL;
}
static u64 svm_get_segment_base(struct kvm_vcpu *vcpu, int seg)
@@ -934,7 +934,7 @@ static int io_get_override(struct kvm_vcpu *vcpu,
return 0;
*addr_override = 0;
- *seg = 0;
+ *seg = NULL;
for (i = 0; i < ins_length; i++)
switch (inst[i]) {
case 0xf0:
@@ -1087,7 +1087,7 @@ static int cpuid_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
static int emulate_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
- if (emulate_instruction(vcpu, 0, 0, 0) != EMULATE_DONE)
+ if (emulate_instruction(vcpu, NULL, 0, 0) != EMULATE_DONE)
printk(KERN_ERR "%s: failed\n", __FUNCTION__);
return 1;
}
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 54c35c0b3181..27e05a77e21a 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -98,7 +98,7 @@ static struct vmx_msr_entry *find_msr_entry(struct kvm_vcpu *vcpu, u32 msr)
for (i = 0; i < vcpu->nmsrs; ++i)
if (vcpu->guest_msrs[i].index == msr)
return &vcpu->guest_msrs[i];
- return 0;
+ return NULL;
}
static void vmcs_clear(struct vmcs *vmcs)
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c
index 5ed41fe84e57..f83fad2a3ff4 100644
--- a/drivers/macintosh/rack-meter.c
+++ b/drivers/macintosh/rack-meter.c
@@ -171,11 +171,11 @@ static void rackmeter_setup_dbdma(struct rackmeter *rm)
/* Make sure dbdma is reset */
DBDMA_DO_RESET(rm->dma_regs);
- pr_debug("rackmeter: mark offset=0x%lx\n",
+ pr_debug("rackmeter: mark offset=0x%zx\n",
offsetof(struct rackmeter_dma, mark));
- pr_debug("rackmeter: buf1 offset=0x%lx\n",
+ pr_debug("rackmeter: buf1 offset=0x%zx\n",
offsetof(struct rackmeter_dma, buf1));
- pr_debug("rackmeter: buf2 offset=0x%lx\n",
+ pr_debug("rackmeter: buf2 offset=0x%zx\n",
offsetof(struct rackmeter_dma, buf2));
/* Prepare 4 dbdma commands for the 2 buffers */
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
index f51e02fe3655..0e948a5c5a03 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -698,7 +698,6 @@ IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = {
[ 0x29 ] = KEY_TEXT,
[ 0x2a ] = KEY_MEDIA,
[ 0x18 ] = KEY_EPG,
- [ 0x27 ] = KEY_RECORD,
};
EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey);
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 7243337b771a..bdd6301d2a47 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1072,7 +1072,7 @@ static int usbvision_v4l2_ioctl(struct inode *inode, struct file *file,
}
-static ssize_t usbvision_v4l2_read(struct file *file, char *buf,
+static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct video_device *dev = video_devdata(file);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 89bba277da5f..bedae4ad3f74 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -42,7 +42,7 @@ config SGI_IOC4
config TIFM_CORE
tristate "TI Flash Media interface support (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ depends on EXPERIMENTAL && PCI
help
If you want support for Texas Instruments(R) Flash Media adapters
you should select this option and then also choose an appropriate
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index db9d7df75ae0..552b7957a92a 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -108,8 +108,8 @@ static struct jprobe lkdtm;
static int lkdtm_parse_commandline(void);
static void lkdtm_handler(void);
-static char* cpoint_name = INVALID;
-static char* cpoint_type = NONE;
+static char* cpoint_name;
+static char* cpoint_type;
static int cpoint_count = DEFAULT_COUNT;
static int recur_count = REC_NUM_DEFAULT;
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 4224686fdf2a..12af9c718764 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -111,7 +111,7 @@ config MMC_IMX
config MMC_TIFM_SD
tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)"
- depends on MMC && EXPERIMENTAL
+ depends on MMC && EXPERIMENTAL && PCI
select TIFM_CORE
help
Say Y here if you want to be able to access MMC/SD cards with
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 7e34c4f07b70..bc7e906571d3 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -600,8 +600,7 @@ el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring
count -= semi_count;
memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count);
} else {
- /* Packet is in one chunk -- we can copy + cksum. */
- eth_io_copy_and_sum(skb, base + ring_offset, count, 0);
+ memcpy_fromio(skb->data, base + ring_offset, count);
}
return;
}
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b79711d441a4..38f41a593b12 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2335,6 +2335,17 @@ config QLA3XXX
To compile this driver as a module, choose M here: the module
will be called qla3xxx.
+config ATL1
+ tristate "Attansic L1 Gigabit Ethernet support (EXPERIMENTAL)"
+ depends on NET_PCI && PCI && EXPERIMENTAL
+ select CRC32
+ select MII
+ help
+ This driver supports the Attansic L1 gigabit ethernet adapter.
+
+ To compile this driver as a module, choose M here. The module
+ will be called atl1.
+
endmenu
#
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 0878e3df5174..33af833667da 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/
obj-$(CONFIG_CHELSIO_T3) += cxgb3/
obj-$(CONFIG_EHEA) += ehea/
obj-$(CONFIG_BONDING) += bonding/
+obj-$(CONFIG_ATL1) += atl1/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
gianfar_driver-objs := gianfar.o \
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index c01f87f5bed7..644c408515df 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -327,8 +327,7 @@ static void ac_block_input(struct net_device *dev, int count, struct sk_buff *sk
memcpy_fromio(skb->data + semi_count,
ei_status.mem + TX_PAGES*256, count);
} else {
- /* Packet is in one chunk -- we can copy + cksum. */
- eth_io_copy_and_sum(skb, start, count, 0);
+ memcpy_fromio(skb->data, start, count);
}
}
diff --git a/drivers/net/atl1/Makefile b/drivers/net/atl1/Makefile
new file mode 100644
index 000000000000..a6b707e4e69e
--- /dev/null
+++ b/drivers/net/atl1/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ATL1) += atl1.o
+atl1-y += atl1_main.o atl1_hw.o atl1_ethtool.o atl1_param.o
diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h
new file mode 100644
index 000000000000..b1c6034e68fa
--- /dev/null
+++ b/drivers/net/atl1/atl1.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ATL1_H_
+#define _ATL1_H_
+
+#include <linux/types.h>
+#include <linux/if_vlan.h>
+
+#include "atl1_hw.h"
+
+/* function prototypes needed by multiple files */
+s32 atl1_up(struct atl1_adapter *adapter);
+void atl1_down(struct atl1_adapter *adapter);
+int atl1_reset(struct atl1_adapter *adapter);
+s32 atl1_setup_ring_resources(struct atl1_adapter *adapter);
+void atl1_free_ring_resources(struct atl1_adapter *adapter);
+
+extern char atl1_driver_name[];
+extern char atl1_driver_version[];
+extern const struct ethtool_ops atl1_ethtool_ops;
+
+struct atl1_adapter;
+
+#define ATL1_MAX_INTR 3
+
+#define ATL1_DEFAULT_TPD 256
+#define ATL1_MAX_TPD 1024
+#define ATL1_MIN_TPD 64
+#define ATL1_DEFAULT_RFD 512
+#define ATL1_MIN_RFD 128
+#define ATL1_MAX_RFD 2048
+
+#define ATL1_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i]))
+#define ATL1_RFD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_free_desc)
+#define ATL1_TPD_DESC(R, i) ATL1_GET_DESC(R, i, struct tx_packet_desc)
+#define ATL1_RRD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_return_desc)
+
+/*
+ * Some workarounds require millisecond delays and are run during interrupt
+ * context. Most notably, when establishing link, the phy may need tweaking
+ * but cannot process phy register reads/writes faster than millisecond
+ * intervals...and we establish link due to a "link status change" interrupt.
+ */
+
+/*
+ * wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer
+ */
+struct atl1_buffer {
+ struct sk_buff *skb;
+ u16 length;
+ u16 alloced;
+ dma_addr_t dma;
+};
+
+#define MAX_TX_BUF_LEN 0x3000 /* 12KB */
+
+struct atl1_tpd_ring {
+ void *desc; /* pointer to the descriptor ring memory */
+ dma_addr_t dma; /* physical adress of the descriptor ring */
+ u16 size; /* length of descriptor ring in bytes */
+ u16 count; /* number of descriptors in the ring */
+ u16 hw_idx; /* hardware index */
+ atomic_t next_to_clean;
+ atomic_t next_to_use;
+ struct atl1_buffer *buffer_info;
+};
+
+struct atl1_rfd_ring {
+ void *desc;
+ dma_addr_t dma;
+ u16 size;
+ u16 count;
+ atomic_t next_to_use;
+ u16 next_to_clean;
+ struct atl1_buffer *buffer_info;
+};
+
+struct atl1_rrd_ring {
+ void *desc;
+ dma_addr_t dma;
+ unsigned int size;
+ u16 count;
+ u16 next_to_use;
+ atomic_t next_to_clean;
+};
+
+struct atl1_ring_header {
+ void *desc; /* pointer to the descriptor ring memory */
+ dma_addr_t dma; /* physical adress of the descriptor ring */
+ unsigned int size; /* length of descriptor ring in bytes */
+};
+
+struct atl1_cmb {
+ struct coals_msg_block *cmb;
+ dma_addr_t dma;
+};
+
+struct atl1_smb {
+ struct stats_msg_block *smb;
+ dma_addr_t dma;
+};
+
+/* Statistics counters */
+struct atl1_sft_stats {
+ u64 rx_packets;
+ u64 tx_packets;
+ u64 rx_bytes;
+ u64 tx_bytes;
+ u64 multicast;
+ u64 collisions;
+ u64 rx_errors;
+ u64 rx_length_errors;
+ u64 rx_crc_errors;
+ u64 rx_frame_errors;
+ u64 rx_fifo_errors;
+ u64 rx_missed_errors;
+ u64 tx_errors;
+ u64 tx_fifo_errors;
+ u64 tx_aborted_errors;
+ u64 tx_window_errors;
+ u64 tx_carrier_errors;
+
+ u64 tx_pause; /* num Pause packet transmitted. */
+ u64 excecol; /* num tx packets aborted due to excessive collisions. */
+ u64 deffer; /* num deferred tx packets */
+ u64 scc; /* num packets subsequently transmitted successfully w/ single prior collision. */
+ u64 mcc; /* num packets subsequently transmitted successfully w/ multiple prior collisions. */
+ u64 latecol; /* num tx packets w/ late collisions. */
+ u64 tx_underun; /* num tx packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+ u64 tx_trunc; /* num tx packets truncated due to size exceeding MTU, regardless whether truncated by Selene or not. (The name doesn't really reflect the meaning in this case.) */
+ u64 rx_pause; /* num Pause packets received. */
+ u64 rx_rrd_ov;
+ u64 rx_trunc;
+};
+
+/* board specific private data structure */
+#define ATL1_REGS_LEN 8
+
+/* Structure containing variables used by the shared code */
+struct atl1_hw {
+ u8 __iomem *hw_addr;
+ struct atl1_adapter *back;
+ enum atl1_dma_order dma_ord;
+ enum atl1_dma_rcb rcb_value;
+ enum atl1_dma_req_block dmar_block;
+ enum atl1_dma_req_block dmaw_block;
+ u8 preamble_len;
+ u8 max_retry; /* Retransmission maximum, after which the packet will be discarded */
+ u8 jam_ipg; /* IPG to start JAM for collision based flow control in half-duplex mode. In units of 8-bit time */
+ u8 ipgt; /* Desired back to back inter-packet gap. The default is 96-bit time */
+ u8 min_ifg; /* Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped */
+ u8 ipgr1; /* 64bit Carrier-Sense window */
+ u8 ipgr2; /* 96-bit IPG window */
+ u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. Each TPD is 16 bytes long */
+ u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned burst. Each RFD is 12 bytes long */
+ u8 rfd_fetch_gap;
+ u8 rrd_burst; /* Threshold number of RRDs that can be retired in a burst. Each RRD is 16 bytes long */
+ u8 tpd_fetch_th;
+ u8 tpd_fetch_gap;
+ u16 tx_jumbo_task_th;
+ u16 txf_burst; /* Number of data bytes to read in a cache-aligned burst. Each SRAM entry is
+ 8 bytes long */
+ u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN packets should add 4 bytes */
+ u16 rx_jumbo_lkah;
+ u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after every 512ns passes. */
+ u16 lcol; /* Collision Window */
+
+ u16 cmb_tpd;
+ u16 cmb_rrd;
+ u16 cmb_rx_timer;
+ u16 cmb_tx_timer;
+ u32 smb_timer;
+ u16 media_type;
+ u16 autoneg_advertised;
+ u16 pci_cmd_word;
+
+ u16 mii_autoneg_adv_reg;
+ u16 mii_1000t_ctrl_reg;
+
+ u32 mem_rang;
+ u32 txcw;
+ u32 max_frame_size;
+ u32 min_frame_size;
+ u32 mc_filter_type;
+ u32 num_mc_addrs;
+ u32 collision_delta;
+ u32 tx_packet_delta;
+ u16 phy_spd_default;
+
+ u16 dev_rev;
+ u8 revision_id;
+
+ /* spi flash */
+ u8 flash_vendor;
+
+ u8 dma_fairness;
+ u8 mac_addr[ETH_ALEN];
+ u8 perm_mac_addr[ETH_ALEN];
+
+ /* bool phy_preamble_sup; */
+ bool phy_configured;
+};
+
+struct atl1_adapter {
+ /* OS defined structs */
+ struct net_device *netdev;
+ struct pci_dev *pdev;
+ struct net_device_stats net_stats;
+ struct atl1_sft_stats soft_stats;
+
+ struct vlan_group *vlgrp;
+ u32 rx_buffer_len;
+ u32 wol;
+ u16 link_speed;
+ u16 link_duplex;
+ spinlock_t lock;
+ atomic_t irq_sem;
+ struct work_struct tx_timeout_task;
+ struct work_struct link_chg_task;
+ struct work_struct pcie_dma_to_rst_task;
+ struct timer_list watchdog_timer;
+ struct timer_list phy_config_timer;
+ bool phy_timer_pending;
+
+ bool mac_disabled;
+
+ /* All descriptor rings' memory */
+ struct atl1_ring_header ring_header;
+
+ /* TX */
+ struct atl1_tpd_ring tpd_ring;
+ spinlock_t mb_lock;
+
+ /* RX */
+ struct atl1_rfd_ring rfd_ring;
+ struct atl1_rrd_ring rrd_ring;
+ u64 hw_csum_err;
+ u64 hw_csum_good;
+
+ u32 gorcl;
+ u64 gorcl_old;
+
+ /* Interrupt Moderator timer ( 2us resolution) */
+ u16 imt;
+ /* Interrupt Clear timer (2us resolution) */
+ u16 ict;
+
+ /* MII interface info */
+ struct mii_if_info mii;
+
+ /* structs defined in atl1_hw.h */
+ u32 bd_number; /* board number */
+ bool pci_using_64;
+ struct atl1_hw hw;
+ struct atl1_smb smb;
+ struct atl1_cmb cmb;
+
+ u32 pci_state[16];
+};
+
+#endif /* _ATL1_H_ */
diff --git a/drivers/net/atl1/atl1_ethtool.c b/drivers/net/atl1/atl1_ethtool.c
new file mode 100644
index 000000000000..c11c27798e5c
--- /dev/null
+++ b/drivers/net/atl1/atl1_ethtool.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/mii.h>
+#include <asm/uaccess.h>
+
+#include "atl1.h"
+
+struct atl1_stats {
+ char stat_string[ETH_GSTRING_LEN];
+ int sizeof_stat;
+ int stat_offset;
+};
+
+#define ATL1_STAT(m) sizeof(((struct atl1_adapter *)0)->m), \
+ offsetof(struct atl1_adapter, m)
+
+static struct atl1_stats atl1_gstrings_stats[] = {
+ {"rx_packets", ATL1_STAT(soft_stats.rx_packets)},
+ {"tx_packets", ATL1_STAT(soft_stats.tx_packets)},
+ {"rx_bytes", ATL1_STAT(soft_stats.rx_bytes)},
+ {"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
+ {"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
+ {"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
+ {"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
+ {"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
+ {"multicast", ATL1_STAT(soft_stats.multicast)},
+ {"collisions", ATL1_STAT(soft_stats.collisions)},
+ {"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
+ {"rx_over_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+ {"rx_crc_errors", ATL1_STAT(soft_stats.rx_crc_errors)},
+ {"rx_frame_errors", ATL1_STAT(soft_stats.rx_frame_errors)},
+ {"rx_fifo_errors", ATL1_STAT(soft_stats.rx_fifo_errors)},
+ {"rx_missed_errors", ATL1_STAT(soft_stats.rx_missed_errors)},
+ {"tx_aborted_errors", ATL1_STAT(soft_stats.tx_aborted_errors)},
+ {"tx_carrier_errors", ATL1_STAT(soft_stats.tx_carrier_errors)},
+ {"tx_fifo_errors", ATL1_STAT(soft_stats.tx_fifo_errors)},
+ {"tx_window_errors", ATL1_STAT(soft_stats.tx_window_errors)},
+ {"tx_abort_exce_coll", ATL1_STAT(soft_stats.excecol)},
+ {"tx_abort_late_coll", ATL1_STAT(soft_stats.latecol)},
+ {"tx_deferred_ok", ATL1_STAT(soft_stats.deffer)},
+ {"tx_single_coll_ok", ATL1_STAT(soft_stats.scc)},
+ {"tx_multi_coll_ok", ATL1_STAT(soft_stats.mcc)},
+ {"tx_underun", ATL1_STAT(soft_stats.tx_underun)},
+ {"tx_trunc", ATL1_STAT(soft_stats.tx_trunc)},
+ {"tx_pause", ATL1_STAT(soft_stats.tx_pause)},
+ {"rx_pause", ATL1_STAT(soft_stats.rx_pause)},
+ {"rx_rrd_ov", ATL1_STAT(soft_stats.rx_rrd_ov)},
+ {"rx_trunc", ATL1_STAT(soft_stats.rx_trunc)}
+};
+
+static void atl1_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ int i;
+ char *p;
+
+ for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+ p = (char *)adapter+atl1_gstrings_stats[i].stat_offset;
+ data[i] = (atl1_gstrings_stats[i].sizeof_stat ==
+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
+ }
+
+}
+
+static int atl1_get_stats_count(struct net_device *netdev)
+{
+ return ARRAY_SIZE(atl1_gstrings_stats);
+}
+
+static int atl1_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_TP);
+ ecmd->advertising = ADVERTISED_TP;
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL) {
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ ecmd->advertising |=
+ (ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Full);
+ }
+ else
+ ecmd->advertising |= (ADVERTISED_1000baseT_Full);
+ }
+ ecmd->port = PORT_TP;
+ ecmd->phy_address = 0;
+ ecmd->transceiver = XCVR_INTERNAL;
+
+ if (netif_carrier_ok(adapter->netdev)) {
+ u16 link_speed, link_duplex;
+ atl1_get_speed_and_duplex(hw, &link_speed, &link_duplex);
+ ecmd->speed = link_speed;
+ if (link_duplex == FULL_DUPLEX)
+ ecmd->duplex = DUPLEX_FULL;
+ else
+ ecmd->duplex = DUPLEX_HALF;
+ } else {
+ ecmd->speed = -1;
+ ecmd->duplex = -1;
+ }
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL)
+ ecmd->autoneg = AUTONEG_ENABLE;
+ else
+ ecmd->autoneg = AUTONEG_DISABLE;
+
+ return 0;
+}
+
+static int atl1_set_settings(struct net_device *netdev,
+ struct ethtool_cmd *ecmd)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+ u16 phy_data;
+ int ret_val = 0;
+ u16 old_media_type = hw->media_type;
+
+ if (netif_running(adapter->netdev)) {
+ printk(KERN_DEBUG "%s: ethtool shutting down adapter\n",
+ atl1_driver_name);
+ atl1_down(adapter);
+ }
+
+ if (ecmd->autoneg == AUTONEG_ENABLE)
+ hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
+ else {
+ if (ecmd->speed == SPEED_1000) {
+ if (ecmd->duplex != DUPLEX_FULL) {
+ printk(KERN_WARNING
+ "%s: can't force to 1000M half duplex\n",
+ atl1_driver_name);
+ ret_val = -EINVAL;
+ goto exit_sset;
+ }
+ hw->media_type = MEDIA_TYPE_1000M_FULL;
+ } else if (ecmd->speed == SPEED_100) {
+ if (ecmd->duplex == DUPLEX_FULL) {
+ hw->media_type = MEDIA_TYPE_100M_FULL;
+ } else
+ hw->media_type = MEDIA_TYPE_100M_HALF;
+ } else {
+ if (ecmd->duplex == DUPLEX_FULL)
+ hw->media_type = MEDIA_TYPE_10M_FULL;
+ else
+ hw->media_type = MEDIA_TYPE_10M_HALF;
+ }
+ }
+ switch (hw->media_type) {
+ case MEDIA_TYPE_AUTO_SENSOR:
+ ecmd->advertising =
+ ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_Autoneg | ADVERTISED_TP;
+ break;
+ case MEDIA_TYPE_1000M_FULL:
+ ecmd->advertising =
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_Autoneg | ADVERTISED_TP;
+ break;
+ default:
+ ecmd->advertising = 0;
+ break;
+ }
+ if (atl1_phy_setup_autoneg_adv(hw)) {
+ ret_val = -EINVAL;
+ printk(KERN_WARNING
+ "%s: invalid ethtool speed/duplex setting\n",
+ atl1_driver_name);
+ goto exit_sset;
+ }
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL)
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+ else {
+ switch (hw->media_type) {
+ case MEDIA_TYPE_100M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+ MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ default: /* MEDIA_TYPE_10M_HALF: */
+ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ }
+ }
+ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+exit_sset:
+ if (ret_val)
+ hw->media_type = old_media_type;
+
+ if (netif_running(adapter->netdev)) {
+ printk(KERN_DEBUG "%s: ethtool starting adapter\n",
+ atl1_driver_name);
+ atl1_up(adapter);
+ } else if (!ret_val) {
+ printk(KERN_DEBUG "%s: ethtool resetting adapter\n",
+ atl1_driver_name);
+ atl1_reset(adapter);
+ }
+ return ret_val;
+}
+
+static void atl1_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ strncpy(drvinfo->driver, atl1_driver_name, sizeof(drvinfo->driver));
+ strncpy(drvinfo->version, atl1_driver_version,
+ sizeof(drvinfo->version));
+ strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+ strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+ sizeof(drvinfo->bus_info));
+ drvinfo->eedump_len = ATL1_EEDUMP_LEN;
+}
+
+static void atl1_get_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+ wol->wolopts = 0;
+ if (adapter->wol & ATL1_WUFC_EX)
+ wol->wolopts |= WAKE_UCAST;
+ if (adapter->wol & ATL1_WUFC_MC)
+ wol->wolopts |= WAKE_MCAST;
+ if (adapter->wol & ATL1_WUFC_BC)
+ wol->wolopts |= WAKE_BCAST;
+ if (adapter->wol & ATL1_WUFC_MAG)
+ wol->wolopts |= WAKE_MAGIC;
+ return;
+}
+
+static int atl1_set_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+ return -EOPNOTSUPP;
+ adapter->wol = 0;
+ if (wol->wolopts & WAKE_UCAST)
+ adapter->wol |= ATL1_WUFC_EX;
+ if (wol->wolopts & WAKE_MCAST)
+ adapter->wol |= ATL1_WUFC_MC;
+ if (wol->wolopts & WAKE_BCAST)
+ adapter->wol |= ATL1_WUFC_BC;
+ if (wol->wolopts & WAKE_MAGIC)
+ adapter->wol |= ATL1_WUFC_MAG;
+ return 0;
+}
+
+static void atl1_get_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_tpd_ring *txdr = &adapter->tpd_ring;
+ struct atl1_rfd_ring *rxdr = &adapter->rfd_ring;
+
+ ring->rx_max_pending = ATL1_MAX_RFD;
+ ring->tx_max_pending = ATL1_MAX_TPD;
+ ring->rx_mini_max_pending = 0;
+ ring->rx_jumbo_max_pending = 0;
+ ring->rx_pending = rxdr->count;
+ ring->tx_pending = txdr->count;
+ ring->rx_mini_pending = 0;
+ ring->rx_jumbo_pending = 0;
+}
+
+static int atl1_set_ringparam(struct net_device *netdev,
+ struct ethtool_ringparam *ring)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_tpd_ring *tpdr = &adapter->tpd_ring;
+ struct atl1_rrd_ring *rrdr = &adapter->rrd_ring;
+ struct atl1_rfd_ring *rfdr = &adapter->rfd_ring;
+
+ struct atl1_tpd_ring tpd_old, tpd_new;
+ struct atl1_rfd_ring rfd_old, rfd_new;
+ struct atl1_rrd_ring rrd_old, rrd_new;
+ struct atl1_ring_header rhdr_old, rhdr_new;
+ int err;
+
+ tpd_old = adapter->tpd_ring;
+ rfd_old = adapter->rfd_ring;
+ rrd_old = adapter->rrd_ring;
+ rhdr_old = adapter->ring_header;
+
+ if (netif_running(adapter->netdev))
+ atl1_down(adapter);
+
+ rfdr->count = (u16) max(ring->rx_pending, (u32) ATL1_MIN_RFD);
+ rfdr->count = rfdr->count > ATL1_MAX_RFD ? ATL1_MAX_RFD :
+ rfdr->count;
+ rfdr->count = (rfdr->count + 3) & ~3;
+ rrdr->count = rfdr->count;
+
+ tpdr->count = (u16) max(ring->tx_pending, (u32) ATL1_MIN_TPD);
+ tpdr->count = tpdr->count > ATL1_MAX_TPD ? ATL1_MAX_TPD :
+ tpdr->count;
+ tpdr->count = (tpdr->count + 3) & ~3;
+
+ if (netif_running(adapter->netdev)) {
+ /* try to get new resources before deleting old */
+ err = atl1_setup_ring_resources(adapter);
+ if (err)
+ goto err_setup_ring;
+
+ /*
+ * save the new, restore the old in order to free it,
+ * then restore the new back again
+ */
+
+ rfd_new = adapter->rfd_ring;
+ rrd_new = adapter->rrd_ring;
+ tpd_new = adapter->tpd_ring;
+ rhdr_new = adapter->ring_header;
+ adapter->rfd_ring = rfd_old;
+ adapter->rrd_ring = rrd_old;
+ adapter->tpd_ring = tpd_old;
+ adapter->ring_header = rhdr_old;
+ atl1_free_ring_resources(adapter);
+ adapter->rfd_ring = rfd_new;
+ adapter->rrd_ring = rrd_new;
+ adapter->tpd_ring = tpd_new;
+ adapter->ring_header = rhdr_new;
+
+ err = atl1_up(adapter);
+ if (err)
+ return err;
+ }
+ return 0;
+
+err_setup_ring:
+ adapter->rfd_ring = rfd_old;
+ adapter->rrd_ring = rrd_old;
+ adapter->tpd_ring = tpd_old;
+ adapter->ring_header = rhdr_old;
+ atl1_up(adapter);
+ return err;
+}
+
+static void atl1_get_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *epause)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL) {
+ epause->autoneg = AUTONEG_ENABLE;
+ } else {
+ epause->autoneg = AUTONEG_DISABLE;
+ }
+ epause->rx_pause = 1;
+ epause->tx_pause = 1;
+}
+
+static int atl1_set_pauseparam(struct net_device *netdev,
+ struct ethtool_pauseparam *epause)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL) {
+ epause->autoneg = AUTONEG_ENABLE;
+ } else {
+ epause->autoneg = AUTONEG_DISABLE;
+ }
+
+ epause->rx_pause = 1;
+ epause->tx_pause = 1;
+
+ return 0;
+}
+
+static u32 atl1_get_rx_csum(struct net_device *netdev)
+{
+ return 1;
+}
+
+static void atl1_get_strings(struct net_device *netdev, u32 stringset,
+ u8 *data)
+{
+ u8 *p = data;
+ int i;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < ARRAY_SIZE(atl1_gstrings_stats); i++) {
+ memcpy(p, atl1_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+ break;
+ }
+}
+
+static int atl1_nway_reset(struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+
+ if (netif_running(netdev)) {
+ u16 phy_data;
+ atl1_down(adapter);
+
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL) {
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+ } else {
+ switch (hw->media_type) {
+ case MEDIA_TYPE_100M_FULL:
+ phy_data = MII_CR_FULL_DUPLEX |
+ MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ phy_data = MII_CR_FULL_DUPLEX |
+ MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ default: /* MEDIA_TYPE_10M_HALF */
+ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+ }
+ }
+ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+ atl1_up(adapter);
+ }
+ return 0;
+}
+
+const struct ethtool_ops atl1_ethtool_ops = {
+ .get_settings = atl1_get_settings,
+ .set_settings = atl1_set_settings,
+ .get_drvinfo = atl1_get_drvinfo,
+ .get_wol = atl1_get_wol,
+ .set_wol = atl1_set_wol,
+ .get_ringparam = atl1_get_ringparam,
+ .set_ringparam = atl1_set_ringparam,
+ .get_pauseparam = atl1_get_pauseparam,
+ .set_pauseparam = atl1_set_pauseparam,
+ .get_rx_csum = atl1_get_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_hw_csum,
+ .get_link = ethtool_op_get_link,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_strings = atl1_get_strings,
+ .nway_reset = atl1_nway_reset,
+ .get_ethtool_stats = atl1_get_ethtool_stats,
+ .get_stats_count = atl1_get_stats_count,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ethtool_op_set_tso,
+};
diff --git a/drivers/net/atl1/atl1_hw.c b/drivers/net/atl1/atl1_hw.c
new file mode 100644
index 000000000000..08b2d785469d
--- /dev/null
+++ b/drivers/net/atl1/atl1_hw.c
@@ -0,0 +1,718 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/if_vlan.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32.h>
+#include <asm/byteorder.h>
+
+#include "atl1.h"
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : ATL1_SUCCESS or idle status (if error)
+ */
+s32 atl1_reset_hw(struct atl1_hw *hw)
+{
+ u32 icr;
+ int i;
+
+ /*
+ * Clear Interrupt mask to stop board from generating
+ * interrupts & Clear any pending interrupt events
+ */
+ /*
+ * iowrite32(0, hw->hw_addr + REG_IMR);
+ * iowrite32(0xffffffff, hw->hw_addr + REG_ISR);
+ */
+
+ /*
+ * Issue Soft Reset to the MAC. This will reset the chip's
+ * transmit, receive, DMA. It will not effect
+ * the current PCI configuration. The global reset bit is self-
+ * clearing, and should clear within a microsecond.
+ */
+ iowrite32(MASTER_CTRL_SOFT_RST, hw->hw_addr + REG_MASTER_CTRL);
+ ioread32(hw->hw_addr + REG_MASTER_CTRL);
+
+ iowrite16(1, hw->hw_addr + REG_GPHY_ENABLE);
+ ioread16(hw->hw_addr + REG_GPHY_ENABLE);
+
+ msleep(1); /* delay about 1ms */
+
+ /* Wait at least 10ms for All module to be Idle */
+ for (i = 0; i < 10; i++) {
+ icr = ioread32(hw->hw_addr + REG_IDLE_STATUS);
+ if (!icr)
+ break;
+ msleep(1); /* delay 1 ms */
+ cpu_relax(); /* FIXME: is this still the right way to do this? */
+ }
+
+ if (icr) {
+ printk (KERN_DEBUG "icr = %x\n", icr);
+ return icr;
+ }
+
+ return ATL1_SUCCESS;
+}
+
+/* function about EEPROM
+ *
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+static int atl1_check_eeprom_exist(struct atl1_hw *hw)
+{
+ u32 value;
+ value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+ if (value & SPI_FLASH_CTRL_EN_VPD) {
+ value &= ~SPI_FLASH_CTRL_EN_VPD;
+ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+ }
+
+ value = ioread16(hw->hw_addr + REG_PCIE_CAP_LIST);
+ return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+static bool atl1_read_eeprom(struct atl1_hw *hw, u32 offset, u32 *p_value)
+{
+ int i;
+ u32 control;
+
+ if (offset & 3)
+ return false; /* address do not align */
+
+ iowrite32(0, hw->hw_addr + REG_VPD_DATA);
+ control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+ iowrite32(control, hw->hw_addr + REG_VPD_CAP);
+ ioread32(hw->hw_addr + REG_VPD_CAP);
+
+ for (i = 0; i < 10; i++) {
+ msleep(2);
+ control = ioread32(hw->hw_addr + REG_VPD_CAP);
+ if (control & VPD_CAP_VPD_FLAG)
+ break;
+ }
+ if (control & VPD_CAP_VPD_FLAG) {
+ *p_value = ioread32(hw->hw_addr + REG_VPD_DATA);
+ return true;
+ }
+ return false; /* timeout */
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+ u32 val;
+ int i;
+
+ val = ((u32) (reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+ MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | MDIO_CLK_25_4 <<
+ MDIO_CLK_SEL_SHIFT;
+ iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+ ioread32(hw->hw_addr + REG_MDIO_CTRL);
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+ if (!(val & (MDIO_START | MDIO_BUSY))) {
+ *phy_data = (u16) val;
+ return ATL1_SUCCESS;
+ }
+ return ATL1_ERR_PHY;
+}
+
+#define CUSTOM_SPI_CS_SETUP 2
+#define CUSTOM_SPI_CLK_HI 2
+#define CUSTOM_SPI_CLK_LO 2
+#define CUSTOM_SPI_CS_HOLD 2
+#define CUSTOM_SPI_CS_HI 3
+
+static bool atl1_spi_read(struct atl1_hw *hw, u32 addr, u32 *buf)
+{
+ int i;
+ u32 value;
+
+ iowrite32(0, hw->hw_addr + REG_SPI_DATA);
+ iowrite32(addr, hw->hw_addr + REG_SPI_ADDR);
+
+ value = SPI_FLASH_CTRL_WAIT_READY |
+ (CUSTOM_SPI_CS_SETUP & SPI_FLASH_CTRL_CS_SETUP_MASK) <<
+ SPI_FLASH_CTRL_CS_SETUP_SHIFT | (CUSTOM_SPI_CLK_HI &
+ SPI_FLASH_CTRL_CLK_HI_MASK) <<
+ SPI_FLASH_CTRL_CLK_HI_SHIFT | (CUSTOM_SPI_CLK_LO &
+ SPI_FLASH_CTRL_CLK_LO_MASK) <<
+ SPI_FLASH_CTRL_CLK_LO_SHIFT | (CUSTOM_SPI_CS_HOLD &
+ SPI_FLASH_CTRL_CS_HOLD_MASK) <<
+ SPI_FLASH_CTRL_CS_HOLD_SHIFT | (CUSTOM_SPI_CS_HI &
+ SPI_FLASH_CTRL_CS_HI_MASK) <<
+ SPI_FLASH_CTRL_CS_HI_SHIFT | (1 & SPI_FLASH_CTRL_INS_MASK) <<
+ SPI_FLASH_CTRL_INS_SHIFT;
+
+ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+
+ value |= SPI_FLASH_CTRL_START;
+ iowrite32(value, hw->hw_addr + REG_SPI_FLASH_CTRL);
+ ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+
+ for (i = 0; i < 10; i++) {
+ msleep(1); /* 1ms */
+ value = ioread32(hw->hw_addr + REG_SPI_FLASH_CTRL);
+ if (!(value & SPI_FLASH_CTRL_START))
+ break;
+ }
+
+ if (value & SPI_FLASH_CTRL_START)
+ return false;
+
+ *buf = ioread32(hw->hw_addr + REG_SPI_DATA);
+
+ return true;
+}
+
+/*
+ * get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1_get_permanent_address(struct atl1_hw *hw)
+{
+ u32 addr[2];
+ u32 i, control;
+ u16 reg;
+ u8 eth_addr[ETH_ALEN];
+ bool key_valid;
+
+ if (is_valid_ether_addr(hw->perm_mac_addr))
+ return 0;
+
+ /* init */
+ addr[0] = addr[1] = 0;
+
+ if (!atl1_check_eeprom_exist(hw)) { /* eeprom exist */
+ reg = 0;
+ key_valid = false;
+ /* Read out all EEPROM content */
+ i = 0;
+ while (1) {
+ if (atl1_read_eeprom(hw, i + 0x100, &control)) {
+ if (key_valid) {
+ if (reg == REG_MAC_STA_ADDR)
+ addr[0] = control;
+ else if (reg == (REG_MAC_STA_ADDR + 4))
+ addr[1] = control;
+ key_valid = false;
+ } else if ((control & 0xff) == 0x5A) {
+ key_valid = true;
+ reg = (u16) (control >> 16);
+ } else
+ break; /* assume data end while encount an invalid KEYWORD */
+ } else
+ break; /* read error */
+ i += 4;
+ }
+
+/*
+ * The following 2 lines are the Attansic originals. Saving for posterity.
+ * *(u32 *) & eth_addr[2] = LONGSWAP(addr[0]);
+ * *(u16 *) & eth_addr[0] = SHORTSWAP(*(u16 *) & addr[1]);
+ */
+ *(u32 *) & eth_addr[2] = swab32(addr[0]);
+ *(u16 *) & eth_addr[0] = swab16(*(u16 *) & addr[1]);
+
+ if (is_valid_ether_addr(eth_addr)) {
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+ }
+ return 1;
+ }
+
+ /* see if SPI FLAGS exist ? */
+ addr[0] = addr[1] = 0;
+ reg = 0;
+ key_valid = false;
+ i = 0;
+ while (1) {
+ if (atl1_spi_read(hw, i + 0x1f000, &control)) {
+ if (key_valid) {
+ if (reg == REG_MAC_STA_ADDR)
+ addr[0] = control;
+ else if (reg == (REG_MAC_STA_ADDR + 4))
+ addr[1] = control;
+ key_valid = false;
+ } else if ((control & 0xff) == 0x5A) {
+ key_valid = true;
+ reg = (u16) (control >> 16);
+ } else
+ break; /* data end */
+ } else
+ break; /* read error */
+ i += 4;
+ }
+
+/*
+ * The following 2 lines are the Attansic originals. Saving for posterity.
+ * *(u32 *) & eth_addr[2] = LONGSWAP(addr[0]);
+ * *(u16 *) & eth_addr[0] = SHORTSWAP(*(u16 *) & addr[1]);
+ */
+ *(u32 *) & eth_addr[2] = swab32(addr[0]);
+ *(u16 *) & eth_addr[0] = swab16(*(u16 *) & addr[1]);
+ if (is_valid_ether_addr(eth_addr)) {
+ memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ * hw - Struct containing variables accessed by shared code
+ */
+s32 atl1_read_mac_addr(struct atl1_hw *hw)
+{
+ u16 i;
+
+ if (atl1_get_permanent_address(hw))
+ random_ether_addr(hw->perm_mac_addr);
+
+ for (i = 0; i < ETH_ALEN; i++)
+ hw->mac_addr[i] = hw->perm_mac_addr[i];
+ return ATL1_SUCCESS;
+}
+
+/*
+ * Hashes an address to determine its location in the multicast table
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash
+ *
+ * atl1_hash_mc_addr
+ * purpose
+ * set hash value for a multicast address
+ * hash calcu processing :
+ * 1. calcu 32bit CRC for multicast address
+ * 2. reverse crc with MSB to LSB
+ */
+u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr)
+{
+ u32 crc32, value = 0;
+ int i;
+
+ crc32 = ether_crc_le(6, mc_addr);
+ crc32 = ~crc32;
+ for (i = 0; i < 32; i++)
+ value |= (((crc32 >> i) & 1) << (31 - i));
+
+ return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1_hash_set(struct atl1_hw *hw, u32 hash_value)
+{
+ u32 hash_bit, hash_reg;
+ u32 mta;
+
+ /*
+ * The HASH Table is a register array of 2 32-bit registers.
+ * It is treated like an array of 64 bits. We want to set
+ * bit BitArray[hash_value]. So we figure out what register
+ * the bit is in, read it, OR in the new bit, then write
+ * back the new value. The register is determined by the
+ * upper 7 bits of the hash value and the bit within that
+ * register are determined by the lower 5 bits of the value.
+ */
+ hash_reg = (hash_value >> 31) & 0x1;
+ hash_bit = (hash_value >> 26) & 0x1F;
+ mta = ioread32((hw + REG_RX_HASH_TABLE) + (hash_reg << 2));
+ mta |= (1 << hash_bit);
+ iowrite32(mta, (hw->hw_addr + REG_RX_HASH_TABLE) + (hash_reg << 2));
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data)
+{
+ int i;
+ u32 val;
+
+ val = ((u32) (phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+ (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+ MDIO_SUP_PREAMBLE |
+ MDIO_START | MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+ iowrite32(val, hw->hw_addr + REG_MDIO_CTRL);
+ ioread32(hw->hw_addr + REG_MDIO_CTRL);
+
+ for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+ udelay(2);
+ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ return ATL1_SUCCESS;
+
+ return ATL1_ERR_PHY;
+}
+
+/*
+ * Make L001's PHY out of Power Saving State (bug)
+ * hw - Struct containing variables accessed by shared code
+ * when power on, L001's PHY always on Power saving State
+ * (Gigabit Link forbidden)
+ */
+static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw)
+{
+ s32 ret;
+ ret = atl1_write_phy_reg(hw, 29, 0x0029);
+ if (ret)
+ return ret;
+ return atl1_write_phy_reg(hw, 30, 0);
+}
+
+/*
+ *TODO: do something or get rid of this
+ */
+s32 atl1_phy_enter_power_saving(struct atl1_hw *hw)
+{
+/* s32 ret_val;
+ * u16 phy_data;
+ */
+
+/*
+ ret_val = atl1_write_phy_reg(hw, ...);
+ ret_val = atl1_write_phy_reg(hw, ...);
+ ....
+*/
+ return ATL1_SUCCESS;
+}
+
+/*
+ * Resets the PHY and make all config validate
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII Control regiser (for F001 bug)
+ */
+static s32 atl1_phy_reset(struct atl1_hw *hw)
+{
+ s32 ret_val;
+ u16 phy_data;
+
+ if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
+ hw->media_type == MEDIA_TYPE_1000M_FULL)
+ phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN;
+ else {
+ switch (hw->media_type) {
+ case MEDIA_TYPE_100M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+ MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ default: /* MEDIA_TYPE_10M_HALF: */
+ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ }
+ }
+
+ ret_val = atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+ if (ret_val) {
+ u32 val;
+ int i;
+ /* pcie serdes link may be down! */
+ printk(KERN_DEBUG "%s: autoneg caused pcie phy link down\n",
+ atl1_driver_name);
+
+ for (i = 0; i < 25; i++) {
+ msleep(1);
+ val = ioread32(hw->hw_addr + REG_MDIO_CTRL);
+ if (!(val & (MDIO_START | MDIO_BUSY)))
+ break;
+ }
+
+ if ((val & (MDIO_START | MDIO_BUSY)) != 0) {
+ printk(KERN_WARNING
+ "%s: pcie link down at least for 25ms\n",
+ atl1_driver_name);
+ return ret_val;
+ }
+ }
+ return ATL1_SUCCESS;
+}
+
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ * hw - Struct containing variables accessed by shared code
+ */
+s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw)
+{
+ s32 ret_val;
+ s16 mii_autoneg_adv_reg;
+ s16 mii_1000t_ctrl_reg;
+
+ /* Read the MII Auto-Neg Advertisement Register (Address 4). */
+ mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+
+ /*
+ * First we clear all the 10/100 mb speed bits in the Auto-Neg
+ * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ * the 1000Base-T Control Register (Address 9).
+ */
+ mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+ mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK;
+
+ /*
+ * Need to parse media_type and set up
+ * the appropriate PHY registers.
+ */
+ switch (hw->media_type) {
+ case MEDIA_TYPE_AUTO_SENSOR:
+ mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS |
+ MII_AR_10T_FD_CAPS |
+ MII_AR_100TX_HD_CAPS |
+ MII_AR_100TX_FD_CAPS);
+ mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+ break;
+
+ case MEDIA_TYPE_1000M_FULL:
+ mii_1000t_ctrl_reg |= MII_AT001_CR_1000T_FD_CAPS;
+ break;
+
+ case MEDIA_TYPE_100M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_100TX_FD_CAPS;
+ break;
+
+ case MEDIA_TYPE_100M_HALF:
+ mii_autoneg_adv_reg |= MII_AR_100TX_HD_CAPS;
+ break;
+
+ case MEDIA_TYPE_10M_FULL:
+ mii_autoneg_adv_reg |= MII_AR_10T_FD_CAPS;
+ break;
+
+ default:
+ mii_autoneg_adv_reg |= MII_AR_10T_HD_CAPS;
+ break;
+ }
+
+ /* flow control fixed to enable all */
+ mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+ hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+ hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg;
+
+ ret_val = atl1_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = atl1_write_phy_reg(hw, MII_AT001_CR, mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
+
+ return ATL1_SUCCESS;
+}
+
+/*
+ * Configures link settings.
+ * hw - Struct containing variables accessed by shared code
+ * Assumes the hardware has previously been reset and the
+ * transmitter and receiver are not enabled.
+ */
+static s32 atl1_setup_link(struct atl1_hw *hw)
+{
+ s32 ret_val;
+
+ /*
+ * Options:
+ * PHY will advertise value(s) parsed from
+ * autoneg_advertised and fc
+ * no matter what autoneg is , We will not wait link result.
+ */
+ ret_val = atl1_phy_setup_autoneg_adv(hw);
+ if (ret_val) {
+ printk(KERN_DEBUG "%s: error setting up autonegotiation\n",
+ atl1_driver_name);
+ return ret_val;
+ }
+ /* SW.Reset , En-Auto-Neg if needed */
+ ret_val = atl1_phy_reset(hw);
+ if (ret_val) {
+ printk(KERN_DEBUG "%s: error resetting the phy\n",
+ atl1_driver_name);
+ return ret_val;
+ }
+ hw->phy_configured = true;
+ return ret_val;
+}
+
+static struct atl1_spi_flash_dev flash_table[] = {
+/* MFR_NAME WRSR READ PRGM WREN WRDI RDSR RDID SECTOR_ERASE CHIP_ERASE */
+ {"Atmel", 0x00, 0x03, 0x02, 0x06, 0x04, 0x05, 0x15, 0x52, 0x62},
+ {"SST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0x90, 0x20, 0x60},
+ {"ST", 0x01, 0x03, 0x02, 0x06, 0x04, 0x05, 0xAB, 0xD8, 0xC7},
+};
+
+static void atl1_init_flash_opcode(struct atl1_hw *hw)
+{
+ if (hw->flash_vendor >= sizeof(flash_table) / sizeof(flash_table[0]))
+ hw->flash_vendor = 0; /* ATMEL */
+
+ /* Init OP table */
+ iowrite8(flash_table[hw->flash_vendor].cmd_program,
+ hw->hw_addr + REG_SPI_FLASH_OP_PROGRAM);
+ iowrite8(flash_table[hw->flash_vendor].cmd_sector_erase,
+ hw->hw_addr + REG_SPI_FLASH_OP_SC_ERASE);
+ iowrite8(flash_table[hw->flash_vendor].cmd_chip_erase,
+ hw->hw_addr + REG_SPI_FLASH_OP_CHIP_ERASE);
+ iowrite8(flash_table[hw->flash_vendor].cmd_rdid,
+ hw->hw_addr + REG_SPI_FLASH_OP_RDID);
+ iowrite8(flash_table[hw->flash_vendor].cmd_wren,
+ hw->hw_addr + REG_SPI_FLASH_OP_WREN);
+ iowrite8(flash_table[hw->flash_vendor].cmd_rdsr,
+ hw->hw_addr + REG_SPI_FLASH_OP_RDSR);
+ iowrite8(flash_table[hw->flash_vendor].cmd_wrsr,
+ hw->hw_addr + REG_SPI_FLASH_OP_WRSR);
+ iowrite8(flash_table[hw->flash_vendor].cmd_read,
+ hw->hw_addr + REG_SPI_FLASH_OP_READ);
+}
+
+/*
+ * Performs basic configuration of the adapter.
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table,
+ * and Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+s32 atl1_init_hw(struct atl1_hw *hw)
+{
+ u32 ret_val = 0;
+
+ /* Zero out the Multicast HASH table */
+ iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+ /* clear the old settings from the multicast hash table */
+ iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+ atl1_init_flash_opcode(hw);
+
+ if (!hw->phy_configured) {
+ /* enable GPHY LinkChange Interrrupt */
+ ret_val = atl1_write_phy_reg(hw, 18, 0xC00);
+ if (ret_val)
+ return ret_val;
+ /* make PHY out of power-saving state */
+ ret_val = atl1_phy_leave_power_saving(hw);
+ if (ret_val)
+ return ret_val;
+ /* Call a subroutine to configure the link */
+ ret_val = atl1_setup_link(hw);
+ }
+ return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex)
+{
+ s32 ret_val;
+ u16 phy_data;
+
+ /* ; --- Read PHY Specific Status Register (17) */
+ ret_val = atl1_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+ return ATL1_ERR_PHY_RES;
+
+ switch (phy_data & MII_AT001_PSSR_SPEED) {
+ case MII_AT001_PSSR_1000MBS:
+ *speed = SPEED_1000;
+ break;
+ case MII_AT001_PSSR_100MBS:
+ *speed = SPEED_100;
+ break;
+ case MII_AT001_PSSR_10MBS:
+ *speed = SPEED_10;
+ break;
+ default:
+ printk(KERN_DEBUG "%s: error getting speed\n",
+ atl1_driver_name);
+ return ATL1_ERR_PHY_SPEED;
+ break;
+ }
+ if (phy_data & MII_AT001_PSSR_DPLX)
+ *duplex = FULL_DUPLEX;
+ else
+ *duplex = HALF_DUPLEX;
+
+ return ATL1_SUCCESS;
+}
+
+void atl1_set_mac_addr(struct atl1_hw *hw)
+{
+ u32 value;
+ /*
+ * 00-0B-6A-F6-00-DC
+ * 0: 6AF600DC 1: 000B
+ * low dword
+ */
+ value = (((u32) hw->mac_addr[2]) << 24) |
+ (((u32) hw->mac_addr[3]) << 16) |
+ (((u32) hw->mac_addr[4]) << 8) | (((u32) hw->mac_addr[5]));
+ iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+ /* high dword */
+ value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+ iowrite32(value, (hw->hw_addr + REG_MAC_STA_ADDR) + (1 << 2));
+}
diff --git a/drivers/net/atl1/atl1_hw.h b/drivers/net/atl1/atl1_hw.h
new file mode 100644
index 000000000000..100c09c66e64
--- /dev/null
+++ b/drivers/net/atl1/atl1_hw.h
@@ -0,0 +1,951 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * There are a lot of defines in here that are unused and/or have cryptic
+ * names. Please leave them alone, as they're the closest thing we have
+ * to a spec from Attansic at present. *ahem* -- CHS
+ */
+
+#ifndef _ATL1_HW_H_
+#define _ATL1_HW_H_
+
+#include <linux/types.h>
+#include <linux/mii.h>
+
+struct atl1_adapter;
+struct atl1_hw;
+
+/* function prototypes needed by multiple files */
+s32 atl1_phy_setup_autoneg_adv(struct atl1_hw *hw);
+s32 atl1_write_phy_reg(struct atl1_hw *hw, u32 reg_addr, u16 phy_data);
+s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
+s32 atl1_read_mac_addr(struct atl1_hw *hw);
+s32 atl1_init_hw(struct atl1_hw *hw);
+s32 atl1_get_speed_and_duplex(struct atl1_hw *hw, u16 *speed, u16 *duplex);
+s32 atl1_set_speed_and_duplex(struct atl1_hw *hw, u16 speed, u16 duplex);
+u32 atl1_hash_mc_addr(struct atl1_hw *hw, u8 *mc_addr);
+void atl1_hash_set(struct atl1_hw *hw, u32 hash_value);
+s32 atl1_read_phy_reg(struct atl1_hw *hw, u16 reg_addr, u16 *phy_data);
+void atl1_set_mac_addr(struct atl1_hw *hw);
+s32 atl1_phy_enter_power_saving(struct atl1_hw *hw);
+s32 atl1_reset_hw(struct atl1_hw *hw);
+void atl1_check_options(struct atl1_adapter *adapter);
+
+/* register definitions */
+#define REG_PCIE_CAP_LIST 0x58
+
+#define REG_VPD_CAP 0x6C
+#define VPD_CAP_ID_MASK 0xff
+#define VPD_CAP_ID_SHIFT 0
+#define VPD_CAP_NEXT_PTR_MASK 0xFF
+#define VPD_CAP_NEXT_PTR_SHIFT 8
+#define VPD_CAP_VPD_ADDR_MASK 0x7FFF
+#define VPD_CAP_VPD_ADDR_SHIFT 16
+#define VPD_CAP_VPD_FLAG 0x80000000
+
+#define REG_VPD_DATA 0x70
+
+#define REG_SPI_FLASH_CTRL 0x200
+#define SPI_FLASH_CTRL_STS_NON_RDY 0x1
+#define SPI_FLASH_CTRL_STS_WEN 0x2
+#define SPI_FLASH_CTRL_STS_WPEN 0x80
+#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF
+#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0
+#define SPI_FLASH_CTRL_INS_MASK 0x7
+#define SPI_FLASH_CTRL_INS_SHIFT 8
+#define SPI_FLASH_CTRL_START 0x800
+#define SPI_FLASH_CTRL_EN_VPD 0x2000
+#define SPI_FLASH_CTRL_LDSTART 0x8000
+#define SPI_FLASH_CTRL_CS_HI_MASK 0x3
+#define SPI_FLASH_CTRL_CS_HI_SHIFT 16
+#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3
+#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18
+#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3
+#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20
+#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3
+#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22
+#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3
+#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24
+#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3
+#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26
+#define SPI_FLASH_CTRL_WAIT_READY 0x10000000
+
+#define REG_SPI_ADDR 0x204
+
+#define REG_SPI_DATA 0x208
+
+#define REG_SPI_FLASH_CONFIG 0x20C
+#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF
+#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0
+#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3
+#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
+#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000
+
+#define REG_SPI_FLASH_OP_PROGRAM 0x210
+#define REG_SPI_FLASH_OP_SC_ERASE 0x211
+#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
+#define REG_SPI_FLASH_OP_RDID 0x213
+#define REG_SPI_FLASH_OP_WREN 0x214
+#define REG_SPI_FLASH_OP_RDSR 0x215
+#define REG_SPI_FLASH_OP_WRSR 0x216
+#define REG_SPI_FLASH_OP_READ 0x217
+
+#define REG_TWSI_CTRL 0x218
+#define TWSI_CTRL_LD_OFFSET_MASK 0xFF
+#define TWSI_CTRL_LD_OFFSET_SHIFT 0
+#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7
+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8
+#define TWSI_CTRL_SW_LDSTART 0x800
+#define TWSI_CTRL_HW_LDSTART 0x1000
+#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F
+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15
+#define TWSI_CTRL_LD_EXIST 0x400000
+#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3
+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23
+#define TWSI_CTRL_FREQ_SEL_100K 0
+#define TWSI_CTRL_FREQ_SEL_200K 1
+#define TWSI_CTRL_FREQ_SEL_300K 2
+#define TWSI_CTRL_FREQ_SEL_400K 3
+#define TWSI_CTRL_SMB_SLV_ADDR
+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3
+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24
+
+#define REG_PCIE_DEV_MISC_CTRL 0x21C
+#define PCIE_DEV_MISC_CTRL_EXT_PIPE 0x2
+#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
+#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
+#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8
+#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10
+
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL 0x1400
+#define MASTER_CTRL_SOFT_RST 0x1
+#define MASTER_CTRL_MTIMER_EN 0x2
+#define MASTER_CTRL_ITIMER_EN 0x4
+#define MASTER_CTRL_MANUAL_INT 0x8
+#define MASTER_CTRL_REV_NUM_SHIFT 16
+#define MASTER_CTRL_REV_NUM_MASK 0xff
+#define MASTER_CTRL_DEV_ID_SHIFT 24
+#define MASTER_CTRL_DEV_ID_MASK 0xff
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT 0x1404
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODU_TIMER_INIT 0x1408
+
+#define REG_GPHY_ENABLE 0x140C
+
+/* IRQ Anti-Lost Timer Initial Value Register */
+#define REG_CMBDISDMA_TIMER 0x140E
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS 0x1410
+#define IDLE_STATUS_RXMAC 1
+#define IDLE_STATUS_TXMAC 2
+#define IDLE_STATUS_RXQ 4
+#define IDLE_STATUS_TXQ 8
+#define IDLE_STATUS_DMAR 0x10
+#define IDLE_STATUS_DMAW 0x20
+#define IDLE_STATUS_SMB 0x40
+#define IDLE_STATUS_CMB 0x80
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL 0x1414
+#define MDIO_DATA_MASK 0xffff
+#define MDIO_DATA_SHIFT 0
+#define MDIO_REG_ADDR_MASK 0x1f
+#define MDIO_REG_ADDR_SHIFT 16
+#define MDIO_RW 0x200000
+#define MDIO_SUP_PREAMBLE 0x400000
+#define MDIO_START 0x800000
+#define MDIO_CLK_SEL_SHIFT 24
+#define MDIO_CLK_25_4 0
+#define MDIO_CLK_25_6 2
+#define MDIO_CLK_25_8 3
+#define MDIO_CLK_25_10 4
+#define MDIO_CLK_25_14 5
+#define MDIO_CLK_25_20 6
+#define MDIO_CLK_25_28 7
+#define MDIO_BUSY 0x8000000
+#define MDIO_WAIT_TIMES 30
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS 0x1418
+
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL 0x141c
+#define BIST0_NOW 0x1
+#define BIST0_SRAM_FAIL 0x2
+#define BIST0_FUSE_FLAG 0x4
+#define REG_BIST1_CTRL 0x1420
+#define BIST1_NOW 0x1
+#define BIST1_SRAM_FAIL 0x2
+#define BIST1_FUSE_FLAG 0x4
+
+/* MAC Control Register */
+#define REG_MAC_CTRL 0x1480
+#define MAC_CTRL_TX_EN 1
+#define MAC_CTRL_RX_EN 2
+#define MAC_CTRL_TX_FLOW 4
+#define MAC_CTRL_RX_FLOW 8
+#define MAC_CTRL_LOOPBACK 0x10
+#define MAC_CTRL_DUPLX 0x20
+#define MAC_CTRL_ADD_CRC 0x40
+#define MAC_CTRL_PAD 0x80
+#define MAC_CTRL_LENCHK 0x100
+#define MAC_CTRL_HUGE_EN 0x200
+#define MAC_CTRL_PRMLEN_SHIFT 10
+#define MAC_CTRL_PRMLEN_MASK 0xf
+#define MAC_CTRL_RMV_VLAN 0x4000
+#define MAC_CTRL_PROMIS_EN 0x8000
+#define MAC_CTRL_TX_PAUSE 0x10000
+#define MAC_CTRL_SCNT 0x20000
+#define MAC_CTRL_SRST_TX 0x40000
+#define MAC_CTRL_TX_SIMURST 0x80000
+#define MAC_CTRL_SPEED_SHIFT 20
+#define MAC_CTRL_SPEED_MASK 0x300000
+#define MAC_CTRL_SPEED_1000 2
+#define MAC_CTRL_SPEED_10_100 1
+#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000
+#define MAC_CTRL_TX_HUGE 0x800000
+#define MAC_CTRL_RX_CHKSUM_EN 0x1000000
+#define MAC_CTRL_MC_ALL_EN 0x2000000
+#define MAC_CTRL_BC_EN 0x4000000
+#define MAC_CTRL_DBG 0x8000000
+
+/* MAC IPG/IFG Control Register */
+#define REG_MAC_IPG_IFG 0x1484
+#define MAC_IPG_IFG_IPGT_SHIFT 0
+#define MAC_IPG_IFG_IPGT_MASK 0x7f
+#define MAC_IPG_IFG_MIFG_SHIFT 8
+#define MAC_IPG_IFG_MIFG_MASK 0xff
+#define MAC_IPG_IFG_IPGR1_SHIFT 16
+#define MAC_IPG_IFG_IPGR1_MASK 0x7f
+#define MAC_IPG_IFG_IPGR2_SHIFT 24
+#define MAC_IPG_IFG_IPGR2_MASK 0x7f
+
+/* MAC STATION ADDRESS */
+#define REG_MAC_STA_ADDR 0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE 0x1490
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL 0x1498
+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0
+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff
+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12
+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf
+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000
+#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000
+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20
+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf
+
+/* Maximum Frame Length Control Register */
+#define REG_MTU 0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL 0x14a0
+#define WOL_PATTERN_EN 0x00000001
+#define WOL_PATTERN_PME_EN 0x00000002
+#define WOL_MAGIC_EN 0x00000004
+#define WOL_MAGIC_PME_EN 0x00000008
+#define WOL_LINK_CHG_EN 0x00000010
+#define WOL_LINK_CHG_PME_EN 0x00000020
+#define WOL_PATTERN_ST 0x00000100
+#define WOL_MAGIC_ST 0x00000200
+#define WOL_LINKCHG_ST 0x00000400
+#define WOL_CLK_SWITCH_EN 0x00008000
+#define WOL_PT0_EN 0x00010000
+#define WOL_PT1_EN 0x00020000
+#define WOL_PT2_EN 0x00040000
+#define WOL_PT3_EN 0x00080000
+#define WOL_PT4_EN 0x00100000
+#define WOL_PT5_EN 0x00200000
+#define WOL_PT6_EN 0x00400000
+
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN 0x14a4
+#define WOL_PT_LEN_MASK 0x7f
+#define WOL_PT0_LEN_SHIFT 0
+#define WOL_PT1_LEN_SHIFT 8
+#define WOL_PT2_LEN_SHIFT 16
+#define WOL_PT3_LEN_SHIFT 24
+#define WOL_PT4_LEN_SHIFT 0
+#define WOL_PT5_LEN_SHIFT 8
+#define WOL_PT6_LEN_SHIFT 16
+
+/* Internal SRAM Partition Register */
+#define REG_SRAM_RFD_ADDR 0x1500
+#define REG_SRAM_RFD_LEN (REG_SRAM_RFD_ADDR+ 4)
+#define REG_SRAM_RRD_ADDR (REG_SRAM_RFD_ADDR+ 8)
+#define REG_SRAM_RRD_LEN (REG_SRAM_RFD_ADDR+12)
+#define REG_SRAM_TPD_ADDR (REG_SRAM_RFD_ADDR+16)
+#define REG_SRAM_TPD_LEN (REG_SRAM_RFD_ADDR+20)
+#define REG_SRAM_TRD_ADDR (REG_SRAM_RFD_ADDR+24)
+#define REG_SRAM_TRD_LEN (REG_SRAM_RFD_ADDR+28)
+#define REG_SRAM_RXF_ADDR (REG_SRAM_RFD_ADDR+32)
+#define REG_SRAM_RXF_LEN (REG_SRAM_RFD_ADDR+36)
+#define REG_SRAM_TXF_ADDR (REG_SRAM_RFD_ADDR+40)
+#define REG_SRAM_TXF_LEN (REG_SRAM_RFD_ADDR+44)
+#define REG_SRAM_TCPH_PATH_ADDR (REG_SRAM_RFD_ADDR+48)
+#define SRAM_TCPH_ADDR_MASK 0x0fff
+#define SRAM_TCPH_ADDR_SHIFT 0
+#define SRAM_PATH_ADDR_MASK 0x0fff
+#define SRAM_PATH_ADDR_SHIFT 16
+
+/* Load Ptr Register */
+#define REG_LOAD_PTR (REG_SRAM_RFD_ADDR+52)
+
+/* Descriptor Control register */
+#define REG_DESC_BASE_ADDR_HI 0x1540
+#define REG_DESC_RFD_ADDR_LO (REG_DESC_BASE_ADDR_HI+4)
+#define REG_DESC_RRD_ADDR_LO (REG_DESC_BASE_ADDR_HI+8)
+#define REG_DESC_TPD_ADDR_LO (REG_DESC_BASE_ADDR_HI+12)
+#define REG_DESC_CMB_ADDR_LO (REG_DESC_BASE_ADDR_HI+16)
+#define REG_DESC_SMB_ADDR_LO (REG_DESC_BASE_ADDR_HI+20)
+#define REG_DESC_RFD_RRD_RING_SIZE (REG_DESC_BASE_ADDR_HI+24)
+#define DESC_RFD_RING_SIZE_MASK 0x7ff
+#define DESC_RFD_RING_SIZE_SHIFT 0
+#define DESC_RRD_RING_SIZE_MASK 0x7ff
+#define DESC_RRD_RING_SIZE_SHIFT 16
+#define REG_DESC_TPD_RING_SIZE (REG_DESC_BASE_ADDR_HI+28)
+#define DESC_TPD_RING_SIZE_MASK 0x3ff
+#define DESC_TPD_RING_SIZE_SHIFT 0
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL 0x1580
+#define TXQ_CTRL_TPD_BURST_NUM_SHIFT 0
+#define TXQ_CTRL_TPD_BURST_NUM_MASK 0x1f
+#define TXQ_CTRL_EN 0x20
+#define TXQ_CTRL_ENH_MODE 0x40
+#define TXQ_CTRL_TPD_FETCH_TH_SHIFT 8
+#define TXQ_CTRL_TPD_FETCH_TH_MASK 0x3f
+#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16
+#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xffff
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_JUMBO_TASK_TH_TPD_IPG 0x1584
+#define TX_JUMBO_TASK_TH_MASK 0x7ff
+#define TX_JUMBO_TASK_TH_SHIFT 0
+#define TX_TPD_MIN_IPG_MASK 0x1f
+#define TX_TPD_MIN_IPG_SHIFT 16
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL 0x15a0
+#define RXQ_CTRL_RFD_BURST_NUM_SHIFT 0
+#define RXQ_CTRL_RFD_BURST_NUM_MASK 0xff
+#define RXQ_CTRL_RRD_BURST_THRESH_SHIFT 8
+#define RXQ_CTRL_RRD_BURST_THRESH_MASK 0xff
+#define RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT 16
+#define RXQ_CTRL_RFD_PREF_MIN_IPG_MASK 0x1f
+#define RXQ_CTRL_CUT_THRU_EN 0x40000000
+#define RXQ_CTRL_EN 0x80000000
+
+/* Rx jumbo packet threshold and rrd retirement timer */
+#define REG_RXQ_JMBOSZ_RRDTIM (REG_RXQ_CTRL+ 4)
+#define RXQ_JMBOSZ_TH_MASK 0x7ff
+#define RXQ_JMBOSZ_TH_SHIFT 0
+#define RXQ_JMBO_LKAH_MASK 0xf
+#define RXQ_JMBO_LKAH_SHIFT 11
+#define RXQ_RRD_TIMER_MASK 0xffff
+#define RXQ_RRD_TIMER_SHIFT 16
+
+/* RFD flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH (REG_RXQ_CTRL+ 8)
+#define RXQ_RXF_PAUSE_TH_HI_SHIFT 16
+#define RXQ_RXF_PAUSE_TH_HI_MASK 0xfff
+#define RXQ_RXF_PAUSE_TH_LO_SHIFT 0
+#define RXQ_RXF_PAUSE_TH_LO_MASK 0xfff
+
+/* RRD flow control register */
+#define REG_RXQ_RRD_PAUSE_THRESH (REG_RXQ_CTRL+12)
+#define RXQ_RRD_PAUSE_TH_HI_SHIFT 0
+#define RXQ_RRD_PAUSE_TH_HI_MASK 0xfff
+#define RXQ_RRD_PAUSE_TH_LO_SHIFT 16
+#define RXQ_RRD_PAUSE_TH_LO_MASK 0xfff
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL 0x15c0
+#define DMA_CTRL_DMAR_IN_ORDER 0x1
+#define DMA_CTRL_DMAR_ENH_ORDER 0x2
+#define DMA_CTRL_DMAR_OUT_ORDER 0x4
+#define DMA_CTRL_RCB_VALUE 0x8
+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4
+#define DMA_CTRL_DMAR_BURST_LEN_MASK 7
+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7
+#define DMA_CTRL_DMAW_BURST_LEN_MASK 7
+#define DMA_CTRL_DMAR_EN 0x400
+#define DMA_CTRL_DMAW_EN 0x800
+
+/* CMB/SMB Control Register */
+#define REG_CSMB_CTRL 0x15d0
+#define CSMB_CTRL_CMB_NOW 1
+#define CSMB_CTRL_SMB_NOW 2
+#define CSMB_CTRL_CMB_EN 4
+#define CSMB_CTRL_SMB_EN 8
+
+/* CMB DMA Write Threshold Register */
+#define REG_CMB_WRITE_TH (REG_CSMB_CTRL+ 4)
+#define CMB_RRD_TH_SHIFT 0
+#define CMB_RRD_TH_MASK 0x7ff
+#define CMB_TPD_TH_SHIFT 16
+#define CMB_TPD_TH_MASK 0x7ff
+
+/* RX/TX count-down timer to trigger CMB-write. 2us resolution. */
+#define REG_CMB_WRITE_TIMER (REG_CSMB_CTRL+ 8)
+#define CMB_RX_TM_SHIFT 0
+#define CMB_RX_TM_MASK 0xffff
+#define CMB_TX_TM_SHIFT 16
+#define CMB_TX_TM_MASK 0xffff
+
+/* Number of packet received since last CMB write */
+#define REG_CMB_RX_PKT_CNT (REG_CSMB_CTRL+12)
+
+/* Number of packet transmitted since last CMB write */
+#define REG_CMB_TX_PKT_CNT (REG_CSMB_CTRL+16)
+
+/* SMB auto DMA timer register */
+#define REG_SMB_TIMER (REG_CSMB_CTRL+20)
+
+/* Mailbox Register */
+#define REG_MAILBOX 0x15f0
+#define MB_RFD_PROD_INDX_SHIFT 0
+#define MB_RFD_PROD_INDX_MASK 0x7ff
+#define MB_RRD_CONS_INDX_SHIFT 11
+#define MB_RRD_CONS_INDX_MASK 0x7ff
+#define MB_TPD_PROD_INDX_SHIFT 22
+#define MB_TPD_PROD_INDX_MASK 0x3ff
+
+/* Interrupt Status Register */
+#define REG_ISR 0x1600
+#define ISR_SMB 1
+#define ISR_TIMER 2
+#define ISR_MANUAL 4
+#define ISR_RXF_OV 8
+#define ISR_RFD_UNRUN 0x10
+#define ISR_RRD_OV 0x20
+#define ISR_TXF_UNRUN 0x40
+#define ISR_LINK 0x80
+#define ISR_HOST_RFD_UNRUN 0x100
+#define ISR_HOST_RRD_OV 0x200
+#define ISR_DMAR_TO_RST 0x400
+#define ISR_DMAW_TO_RST 0x800
+#define ISR_GPHY 0x1000
+#define ISR_RX_PKT 0x10000
+#define ISR_TX_PKT 0x20000
+#define ISR_TX_DMA 0x40000
+#define ISR_RX_DMA 0x80000
+#define ISR_CMB_RX 0x100000
+#define ISR_CMB_TX 0x200000
+#define ISR_MAC_RX 0x400000
+#define ISR_MAC_TX 0x800000
+#define ISR_UR_DETECTED 0x1000000
+#define ISR_FERR_DETECTED 0x2000000
+#define ISR_NFERR_DETECTED 0x4000000
+#define ISR_CERR_DETECTED 0x8000000
+#define ISR_PHY_LINKDOWN 0x10000000
+#define ISR_DIS_SMB 0x20000000
+#define ISR_DIS_DMA 0x40000000
+#define ISR_DIS_INT 0x80000000
+
+/* Interrupt Mask Register */
+#define REG_IMR 0x1604
+
+/* Normal Interrupt mask */
+#define IMR_NORMAL_MASK (\
+ ISR_SMB |\
+ ISR_GPHY |\
+ ISR_PHY_LINKDOWN|\
+ ISR_DMAR_TO_RST |\
+ ISR_DMAW_TO_RST |\
+ ISR_CMB_TX |\
+ ISR_CMB_RX )
+
+/* Debug Interrupt Mask (enable all interrupt) */
+#define IMR_DEBUG_MASK (\
+ ISR_SMB |\
+ ISR_TIMER |\
+ ISR_MANUAL |\
+ ISR_RXF_OV |\
+ ISR_RFD_UNRUN |\
+ ISR_RRD_OV |\
+ ISR_TXF_UNRUN |\
+ ISR_LINK |\
+ ISR_CMB_TX |\
+ ISR_CMB_RX |\
+ ISR_RX_PKT |\
+ ISR_TX_PKT |\
+ ISR_MAC_RX |\
+ ISR_MAC_TX )
+
+/* Interrupt Status Register */
+#define REG_RFD_RRD_IDX 0x1800
+#define REG_TPD_IDX 0x1804
+
+/* MII definition */
+/* PHY Common Register */
+#define MII_AT001_CR 0x09
+#define MII_AT001_SR 0x0A
+#define MII_AT001_ESR 0x0F
+#define MII_AT001_PSCR 0x10
+#define MII_AT001_PSSR 0x11
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_MASK 0x2040
+#define MII_CR_SPEED_1000 0x0040
+#define MII_CR_SPEED_100 0x2000
+#define MII_CR_SPEED_10 0x0000
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+
+/* Link partner ability register. */
+#define MII_LPA_SLCT 0x001f /* Same as advertise selector */
+#define MII_LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define MII_LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define MII_LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define MII_LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define MII_LPA_100BASE4 0x0200 /* 100BASE-T4 */
+#define MII_LPA_PAUSE 0x0400 /* PAUSE */
+#define MII_LPA_ASYPAUSE 0x0800 /* Asymmetrical PAUSE */
+#define MII_LPA_RFAULT 0x2000 /* Link partner faulted */
+#define MII_LPA_LPACK 0x4000 /* Link partner acked us */
+#define MII_LPA_NPAGE 0x8000 /* Next page bit */
+
+/* Autoneg Advertisement Register */
+#define MII_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
+#define MII_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
+#define MII_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
+#define MII_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
+#define MII_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
+#define MII_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
+#define MII_AR_PAUSE 0x0400 /* Pause operation desired */
+#define MII_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
+#define MII_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
+#define MII_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+#define MII_AR_SPEED_MASK 0x01E0
+#define MII_AR_DEFAULT_CAP_MASK 0x0DE0
+
+/* 1000BASE-T Control Register */
+#define MII_AT001_CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
+#define MII_AT001_CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
+#define MII_AT001_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port, 0=DTE device */
+#define MII_AT001_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master, 0=Configure PHY as Slave */
+#define MII_AT001_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value, 0=Automatic Master/Slave config */
+#define MII_AT001_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define MII_AT001_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
+#define MII_AT001_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
+#define MII_AT001_CR_1000T_SPEED_MASK 0x0300
+#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK 0x0300
+
+/* 1000BASE-T Status Register */
+#define MII_AT001_SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
+#define MII_AT001_SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
+#define MII_AT001_SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */
+#define MII_AT001_SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT 12
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT 13
+
+/* Extended Status Register */
+#define MII_AT001_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+#define MII_AT001_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+#define MII_AT001_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+#define MII_AT001_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+
+/* AT001 PHY Specific Control Register */
+#define MII_AT001_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
+#define MII_AT001_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
+#define MII_AT001_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
+#define MII_AT001_PSCR_MAC_POWERDOWN 0x0008
+#define MII_AT001_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, 0=CLK125 toggling */
+#define MII_AT001_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5, Manual MDI configuration */
+#define MII_AT001_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
+#define MII_AT001_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */
+#define MII_AT001_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled all speeds. */
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE 0x0080 /* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T RX Threshold), 0=Normal 10BASE-T RX Threshold */
+#define MII_AT001_PSCR_MII_5BIT_ENABLE 0x0100 /* 1=5-Bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */
+#define MII_AT001_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */
+#define MII_AT001_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
+#define MII_AT001_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
+#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT 1
+#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT 5
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
+
+/* AT001 PHY Specific Status Register */
+#define MII_AT001_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
+#define MII_AT001_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
+#define MII_AT001_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
+#define MII_AT001_PSSR_10MBS 0x0000 /* 00=10Mbs */
+#define MII_AT001_PSSR_100MBS 0x4000 /* 01=100Mbs */
+#define MII_AT001_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
+
+/* PCI Command Register Bit Definitions */
+#define PCI_REG_COMMAND 0x04 /* PCI Command Register */
+#define CMD_IO_SPACE 0x0001
+#define CMD_MEMORY_SPACE 0x0002
+#define CMD_BUS_MASTER 0x0004
+
+/* Wake Up Filter Control */
+#define ATL1_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define ATL1_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
+#define ATL1_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
+#define ATL1_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */
+#define ATL1_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
+
+/* Error Codes */
+#define ATL1_SUCCESS 0
+#define ATL1_ERR_EEPROM 1
+#define ATL1_ERR_PHY 2
+#define ATL1_ERR_CONFIG 3
+#define ATL1_ERR_PARAM 4
+#define ATL1_ERR_MAC_TYPE 5
+#define ATL1_ERR_PHY_TYPE 6
+#define ATL1_ERR_PHY_SPEED 7
+#define ATL1_ERR_PHY_RES 8
+
+#define SPEED_0 0xffff
+#define SPEED_10 10
+#define SPEED_100 100
+#define SPEED_1000 1000
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+#define MEDIA_TYPE_AUTO_SENSOR 0
+#define MEDIA_TYPE_1000M_FULL 1
+#define MEDIA_TYPE_100M_FULL 2
+#define MEDIA_TYPE_100M_HALF 3
+#define MEDIA_TYPE_10M_FULL 4
+#define MEDIA_TYPE_10M_HALF 5
+
+#define ADVERTISE_10_HALF 0x0001
+#define ADVERTISE_10_FULL 0x0002
+#define ADVERTISE_100_HALF 0x0004
+#define ADVERTISE_100_FULL 0x0008
+#define ADVERTISE_1000_HALF 0x0010
+#define ADVERTISE_1000_FULL 0x0020
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */
+#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */
+#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */
+
+/* The size (in bytes) of a ethernet packet */
+#define ENET_HEADER_SIZE 14
+#define MAXIMUM_ETHERNET_FRAME_SIZE 1518 /* with FCS */
+#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* with FCS */
+#define ETHERNET_FCS_SIZE 4
+#define MAX_JUMBO_FRAME_SIZE 0x2800
+
+#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */
+#define PHY_FORCE_TIME 20 /* 2.0 Seconds */
+
+/* For checksumming , the sum of all words in the EEPROM should equal 0xBABA */
+#define EEPROM_SUM 0xBABA
+
+#define ATL1_EEDUMP_LEN 48
+
+/* Statistics counters collected by the MAC */
+struct stats_msg_block {
+ /* rx */
+ u32 rx_ok; /* The number of good packet received. */
+ u32 rx_bcast; /* The number of good broadcast packet received. */
+ u32 rx_mcast; /* The number of good multicast packet received. */
+ u32 rx_pause; /* The number of Pause packet received. */
+ u32 rx_ctrl; /* The number of Control packet received other than Pause frame. */
+ u32 rx_fcs_err; /* The number of packets with bad FCS. */
+ u32 rx_len_err; /* The number of packets with mismatch of length field and actual size. */
+ u32 rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */
+ u32 rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */
+ u32 rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */
+ u32 rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */
+ u32 rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */
+ u32 rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */
+ u32 rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */
+ u32 rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */
+ u32 rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+ u32 rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */
+ u32 rx_sz_ov; /* The number of good and bad packets received that are more than MTU size Å¡C truncated by Selene. */
+ u32 rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */
+ u32 rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */
+ u32 rx_align_err; /* Alignment Error */
+ u32 rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
+ u32 rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
+ u32 rx_err_addr; /* The number of packets dropped due to address filtering. */
+
+ /* tx */
+ u32 tx_ok; /* The number of good packet transmitted. */
+ u32 tx_bcast; /* The number of good broadcast packet transmitted. */
+ u32 tx_mcast; /* The number of good multicast packet transmitted. */
+ u32 tx_pause; /* The number of Pause packet transmitted. */
+ u32 tx_exc_defer; /* The number of packets transmitted with excessive deferral. */
+ u32 tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */
+ u32 tx_defer; /* The number of packets transmitted that is deferred. */
+ u32 tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */
+ u32 tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */
+ u32 tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+ u32 tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+ u32 tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+ u32 tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+ u32 tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+ u32 tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+ u32 tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */
+ u32 tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+ u32 tx_late_col; /* The number of packets transmitted with late collisions. */
+ u32 tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */
+ u32 tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+ u32 tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+ u32 tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */
+ u32 tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */
+ u32 tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */
+ u32 tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */
+ u32 smb_updated; /* 1: SMB Updated. This is used by software as the indication of the statistics update.
+ * Software should clear this bit as soon as retrieving the statistics information. */
+};
+
+/* Coalescing Message Block */
+struct coals_msg_block {
+ u32 int_stats; /* interrupt status */
+ u16 rrd_prod_idx; /* TRD Producer Index. */
+ u16 rfd_cons_idx; /* RFD Consumer Index. */
+ u16 update; /* Selene sets this bit every time it DMA the CMB to host memory.
+ * Software supposes to clear this bit when CMB information is processed. */
+ u16 tpd_cons_idx; /* TPD Consumer Index. */
+};
+
+/* RRD descriptor */
+struct rx_return_desc {
+ u8 num_buf; /* Number of RFD buffers used by the received packet */
+ u8 resved;
+ u16 buf_indx; /* RFD Index of the first buffer */
+ union {
+ u32 valid;
+ struct {
+ u16 rx_chksum;
+ u16 pkt_size;
+ } xsum_sz;
+ } xsz;
+
+ u16 pkt_flg; /* Packet flags */
+ u16 err_flg; /* Error flags */
+ u16 resved2;
+ u16 vlan_tag; /* VLAN TAG */
+};
+
+#define PACKET_FLAG_ETH_TYPE 0x0080
+#define PACKET_FLAG_VLAN_INS 0x0100
+#define PACKET_FLAG_ERR 0x0200
+#define PACKET_FLAG_IPV4 0x0400
+#define PACKET_FLAG_UDP 0x0800
+#define PACKET_FLAG_TCP 0x1000
+#define PACKET_FLAG_BCAST 0x2000
+#define PACKET_FLAG_MCAST 0x4000
+#define PACKET_FLAG_PAUSE 0x8000
+
+#define ERR_FLAG_CRC 0x0001
+#define ERR_FLAG_CODE 0x0002
+#define ERR_FLAG_DRIBBLE 0x0004
+#define ERR_FLAG_RUNT 0x0008
+#define ERR_FLAG_OV 0x0010
+#define ERR_FLAG_TRUNC 0x0020
+#define ERR_FLAG_IP_CHKSUM 0x0040
+#define ERR_FLAG_L4_CHKSUM 0x0080
+#define ERR_FLAG_LEN 0x0100
+#define ERR_FLAG_DES_ADDR 0x0200
+
+/* RFD descriptor */
+struct rx_free_desc {
+ __le64 buffer_addr; /* Address of the descriptor's data buffer */
+ __le16 buf_len; /* Size of the receive buffer in host memory, in byte */
+ u16 coalese; /* Update consumer index to host after the reception of this frame */
+ /* __attribute__ ((packed)) is required */
+} __attribute__ ((packed));
+
+/* tsopu defines */
+#define TSO_PARAM_BUFLEN_MASK 0x3FFF
+#define TSO_PARAM_BUFLEN_SHIFT 0
+#define TSO_PARAM_DMAINT_MASK 0x0001
+#define TSO_PARAM_DMAINT_SHIFT 14
+#define TSO_PARAM_PKTNT_MASK 0x0001
+#define TSO_PARAM_PKTINT_SHIFT 15
+#define TSO_PARAM_VLANTAG_MASK 0xFFFF
+#define TSO_PARAM_VLAN_SHIFT 16
+
+/* tsopl defines */
+#define TSO_PARAM_EOP_MASK 0x0001
+#define TSO_PARAM_EOP_SHIFT 0
+#define TSO_PARAM_COALESCE_MASK 0x0001
+#define TSO_PARAM_COALESCE_SHIFT 1
+#define TSO_PARAM_INSVLAG_MASK 0x0001
+#define TSO_PARAM_INSVLAG_SHIFT 2
+#define TSO_PARAM_CUSTOMCKSUM_MASK 0x0001
+#define TSO_PARAM_CUSTOMCKSUM_SHIFT 3
+#define TSO_PARAM_SEGMENT_MASK 0x0001
+#define TSO_PARAM_SEGMENT_SHIFT 4
+#define TSO_PARAM_IPCKSUM_MASK 0x0001
+#define TSO_PARAM_IPCKSUM_SHIFT 5
+#define TSO_PARAM_TCPCKSUM_MASK 0x0001
+#define TSO_PARAM_TCPCKSUM_SHIFT 6
+#define TSO_PARAM_UDPCKSUM_MASK 0x0001
+#define TSO_PARAM_UDPCKSUM_SHIFT 7
+#define TSO_PARAM_VLANTAGGED_MASK 0x0001
+#define TSO_PARAM_VLANTAGGED_SHIFT 8
+#define TSO_PARAM_ETHTYPE_MASK 0x0001
+#define TSO_PARAM_ETHTYPE_SHIFT 9
+#define TSO_PARAM_IPHL_MASK 0x000F
+#define TSO_PARAM_IPHL_SHIFT 10
+#define TSO_PARAM_TCPHDRLEN_MASK 0x000F
+#define TSO_PARAM_TCPHDRLEN_SHIFT 14
+#define TSO_PARAM_HDRFLAG_MASK 0x0001
+#define TSO_PARAM_HDRFLAG_SHIFT 18
+#define TSO_PARAM_MSS_MASK 0x1FFF
+#define TSO_PARAM_MSS_SHIFT 19
+
+/* csumpu defines */
+#define CSUM_PARAM_BUFLEN_MASK 0x3FFF
+#define CSUM_PARAM_BUFLEN_SHIFT 0
+#define CSUM_PARAM_DMAINT_MASK 0x0001
+#define CSUM_PARAM_DMAINT_SHIFT 14
+#define CSUM_PARAM_PKTINT_MASK 0x0001
+#define CSUM_PARAM_PKTINT_SHIFT 15
+#define CSUM_PARAM_VALANTAG_MASK 0xFFFF
+#define CSUM_PARAM_VALAN_SHIFT 16
+
+/* csumpl defines*/
+#define CSUM_PARAM_EOP_MASK 0x0001
+#define CSUM_PARAM_EOP_SHIFT 0
+#define CSUM_PARAM_COALESCE_MASK 0x0001
+#define CSUM_PARAM_COALESCE_SHIFT 1
+#define CSUM_PARAM_INSVLAG_MASK 0x0001
+#define CSUM_PARAM_INSVLAG_SHIFT 2
+#define CSUM_PARAM_CUSTOMCKSUM_MASK 0x0001
+#define CSUM_PARAM_CUSTOMCKSUM_SHIFT 3
+#define CSUM_PARAM_SEGMENT_MASK 0x0001
+#define CSUM_PARAM_SEGMENT_SHIFT 4
+#define CSUM_PARAM_IPCKSUM_MASK 0x0001
+#define CSUM_PARAM_IPCKSUM_SHIFT 5
+#define CSUM_PARAM_TCPCKSUM_MASK 0x0001
+#define CSUM_PARAM_TCPCKSUM_SHIFT 6
+#define CSUM_PARAM_UDPCKSUM_MASK 0x0001
+#define CSUM_PARAM_UDPCKSUM_SHIFT 7
+#define CSUM_PARAM_VLANTAGGED_MASK 0x0001
+#define CSUM_PARAM_VLANTAGGED_SHIFT 8
+#define CSUM_PARAM_ETHTYPE_MASK 0x0001
+#define CSUM_PARAM_ETHTYPE_SHIFT 9
+#define CSUM_PARAM_IPHL_MASK 0x000F
+#define CSUM_PARAM_IPHL_SHIFT 10
+#define CSUM_PARAM_PLOADOFFSET_MASK 0x00FF
+#define CSUM_PARAM_PLOADOFFSET_SHIFT 16
+#define CSUM_PARAM_XSUMOFFSET_MASK 0x00FF
+#define CSUM_PARAM_XSUMOFFSET_SHIFT 24
+
+/* TPD descriptor */
+struct tso_param {
+ /* The order of these declarations is important -- don't change it */
+ u32 tsopu; /* tso_param upper word */
+ u32 tsopl; /* tso_param lower word */
+};
+
+struct csum_param {
+ /* The order of these declarations is important -- don't change it */
+ u32 csumpu; /* csum_param upper word */
+ u32 csumpl; /* csum_param lower word */
+};
+
+union tpd_descr {
+ u64 data;
+ struct csum_param csum;
+ struct tso_param tso;
+};
+
+struct tx_packet_desc {
+ __le64 buffer_addr;
+ union tpd_descr desc;
+};
+
+/* DMA Order Settings */
+enum atl1_dma_order {
+ atl1_dma_ord_in = 1,
+ atl1_dma_ord_enh = 2,
+ atl1_dma_ord_out = 4
+};
+
+enum atl1_dma_rcb {
+ atl1_rcb_64 = 0,
+ atl1_rcb_128 = 1
+};
+
+enum atl1_dma_req_block {
+ atl1_dma_req_128 = 0,
+ atl1_dma_req_256 = 1,
+ atl1_dma_req_512 = 2,
+ atl1_dam_req_1024 = 3,
+ atl1_dam_req_2048 = 4,
+ atl1_dma_req_4096 = 5
+};
+
+struct atl1_spi_flash_dev {
+ const char *manu_name; /* manufacturer id */
+ /* op-code */
+ u8 cmd_wrsr;
+ u8 cmd_read;
+ u8 cmd_program;
+ u8 cmd_wren;
+ u8 cmd_wrdi;
+ u8 cmd_rdsr;
+ u8 cmd_rdid;
+ u8 cmd_sector_erase;
+ u8 cmd_chip_erase;
+};
+
+#endif /* _ATL1_HW_H_ */
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
new file mode 100644
index 000000000000..6655640eb4ca
--- /dev/null
+++ b/drivers/net/atl1/atl1_main.c
@@ -0,0 +1,2468 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ *
+ * Contact Information:
+ * Xiong Huang <xiong_huang@attansic.com>
+ * Attansic Technology Corp. 3F 147, Xianzheng 9th Road, Zhubei,
+ * Xinzhu 302, TAIWAN, REPUBLIC OF CHINA
+ *
+ * Chris Snook <csnook@redhat.com>
+ * Jay Cliburn <jcliburn@gmail.com>
+ *
+ * This version is adapted from the Attansic reference driver for
+ * inclusion in the Linux kernel. It is currently under heavy development.
+ * A very incomplete list of things that need to be dealt with:
+ *
+ * TODO:
+ * Fix TSO; tx performance is horrible with TSO enabled.
+ * Wake on LAN.
+ * Add more ethtool functions, including set ring parameters.
+ * Fix abstruse irq enable/disable condition described here:
+ * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2
+ *
+ * NEEDS TESTING:
+ * VLAN
+ * multicast
+ * promiscuous mode
+ * interrupt coalescing
+ * SMP torture testing
+ */
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/irqreturn.h>
+#include <linux/workqueue.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
+#include <linux/irqflags.h>
+#include <linux/dma-mapping.h>
+#include <linux/net.h>
+#include <linux/pm.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <net/checksum.h>
+
+#include <asm/atomic.h>
+#include <asm/byteorder.h>
+
+#include "atl1.h"
+
+#define RUN_REALTIME 0
+#define DRIVER_VERSION "2.0.6"
+
+char atl1_driver_name[] = "atl1";
+static const char atl1_driver_string[] = "Attansic L1 Ethernet Network Driver";
+static const char atl1_copyright[] = "Copyright(c) 2005-2006 Attansic Corporation.";
+char atl1_driver_version[] = DRIVER_VERSION;
+
+MODULE_AUTHOR
+ ("Attansic Corporation <xiong_huang@attansic.com>, Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>");
+MODULE_DESCRIPTION("Attansic 1000M Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
+/*
+ * atl1_pci_tbl - PCI Device ID Table
+ */
+static const struct pci_device_id atl1_pci_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1048)},
+ /* required last entry */
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, atl1_pci_tbl);
+
+/*
+ * atl1_sw_init - Initialize general software structures (struct atl1_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
+{
+ struct atl1_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+
+ /* PCI config space info */
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+
+ hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+ hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
+
+ adapter->wol = 0;
+ adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
+ adapter->ict = 50000; /* 100ms */
+ adapter->link_speed = SPEED_0; /* hardware init */
+ adapter->link_duplex = FULL_DUPLEX;
+
+ hw->phy_configured = false;
+ hw->preamble_len = 7;
+ hw->ipgt = 0x60;
+ hw->min_ifg = 0x50;
+ hw->ipgr1 = 0x40;
+ hw->ipgr2 = 0x60;
+ hw->max_retry = 0xf;
+ hw->lcol = 0x37;
+ hw->jam_ipg = 7;
+ hw->rfd_burst = 8;
+ hw->rrd_burst = 8;
+ hw->rfd_fetch_gap = 1;
+ hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
+ hw->rx_jumbo_lkah = 1;
+ hw->rrd_ret_timer = 16;
+ hw->tpd_burst = 4;
+ hw->tpd_fetch_th = 16;
+ hw->txf_burst = 0x100;
+ hw->tx_jumbo_task_th = (hw->max_frame_size + 7) >> 3;
+ hw->tpd_fetch_gap = 1;
+ hw->rcb_value = atl1_rcb_64;
+ hw->dma_ord = atl1_dma_ord_enh;
+ hw->dmar_block = atl1_dma_req_256;
+ hw->dmaw_block = atl1_dma_req_256;
+ hw->cmb_rrd = 4;
+ hw->cmb_tpd = 4;
+ hw->cmb_rx_timer = 1; /* about 2us */
+ hw->cmb_tx_timer = 1; /* about 2us */
+ hw->smb_timer = 100000; /* about 200ms */
+
+ atomic_set(&adapter->irq_sem, 0);
+ spin_lock_init(&adapter->lock);
+ spin_lock_init(&adapter->mb_lock);
+
+ return 0;
+}
+
+/*
+ * atl1_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+s32 atl1_setup_ring_resources(struct atl1_adapter *adapter)
+{
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_ring_header *ring_header = &adapter->ring_header;
+ struct pci_dev *pdev = adapter->pdev;
+ int size;
+ u8 offset = 0;
+
+ size = sizeof(struct atl1_buffer) * (tpd_ring->count + rfd_ring->count);
+ tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
+ if (unlikely(!tpd_ring->buffer_info)) {
+ printk(KERN_WARNING "%s: kzalloc failed , size = D%d\n",
+ atl1_driver_name, size);
+ goto err_nomem;
+ }
+ rfd_ring->buffer_info =
+ (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count);
+
+ /* real ring DMA buffer */
+ ring_header->size = size = sizeof(struct tx_packet_desc) *
+ tpd_ring->count
+ + sizeof(struct rx_free_desc) * rfd_ring->count
+ + sizeof(struct rx_return_desc) * rrd_ring->count
+ + sizeof(struct coals_msg_block)
+ + sizeof(struct stats_msg_block)
+ + 40; /* "40: for 8 bytes align" huh? -- CHS */
+
+ ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
+ &ring_header->dma);
+ if (unlikely(!ring_header->desc)) {
+ printk(KERN_WARNING
+ "%s: pci_alloc_consistent failed, size = D%d\n",
+ atl1_driver_name, size);
+ goto err_nomem;
+ }
+
+ memset(ring_header->desc, 0, ring_header->size);
+
+ /* init TPD ring */
+ tpd_ring->dma = ring_header->dma;
+ offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
+ tpd_ring->dma += offset;
+ tpd_ring->desc = (u8 *) ring_header->desc + offset;
+ tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count;
+ atomic_set(&tpd_ring->next_to_use, 0);
+ atomic_set(&tpd_ring->next_to_clean, 0);
+
+ /* init RFD ring */
+ rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
+ offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
+ rfd_ring->dma += offset;
+ rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset);
+ rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count;
+ rfd_ring->next_to_clean = 0;
+ /* rfd_ring->next_to_use = rfd_ring->count - 1; */
+ atomic_set(&rfd_ring->next_to_use, 0);
+
+ /* init RRD ring */
+ rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
+ offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
+ rrd_ring->dma += offset;
+ rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset);
+ rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count;
+ rrd_ring->next_to_use = 0;
+ atomic_set(&rrd_ring->next_to_clean, 0);
+
+ /* init CMB */
+ adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
+ offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0;
+ adapter->cmb.dma += offset;
+ adapter->cmb.cmb =
+ (struct coals_msg_block *) ((u8 *) rrd_ring->desc +
+ (rrd_ring->size + offset));
+
+ /* init SMB */
+ adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block);
+ offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0;
+ adapter->smb.dma += offset;
+ adapter->smb.smb = (struct stats_msg_block *)
+ ((u8 *) adapter->cmb.cmb + (sizeof(struct coals_msg_block) + offset));
+
+ return ATL1_SUCCESS;
+
+err_nomem:
+ kfree(tpd_ring->buffer_info);
+ return -ENOMEM;
+}
+
+/*
+ * atl1_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static void atl1_irq_enable(struct atl1_adapter *adapter)
+{
+ if (likely(!atomic_dec_and_test(&adapter->irq_sem)))
+ iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR);
+}
+
+static void atl1_clear_phy_int(struct atl1_adapter *adapter)
+{
+ u16 phy_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->lock, flags);
+ atl1_read_phy_reg(&adapter->hw, 19, &phy_data);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+static void atl1_inc_smb(struct atl1_adapter *adapter)
+{
+ struct stats_msg_block *smb = adapter->smb.smb;
+
+ /* Fill out the OS statistics structure */
+ adapter->soft_stats.rx_packets += smb->rx_ok;
+ adapter->soft_stats.tx_packets += smb->tx_ok;
+ adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
+ adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
+ adapter->soft_stats.multicast += smb->rx_mcast;
+ adapter->soft_stats.collisions += (smb->tx_1_col +
+ smb->tx_2_col * 2 +
+ smb->tx_late_col +
+ smb->tx_abort_col *
+ adapter->hw.max_retry);
+
+ /* Rx Errors */
+ adapter->soft_stats.rx_errors += (smb->rx_frag +
+ smb->rx_fcs_err +
+ smb->rx_len_err +
+ smb->rx_sz_ov +
+ smb->rx_rxf_ov +
+ smb->rx_rrd_ov + smb->rx_align_err);
+ adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;
+ adapter->soft_stats.rx_length_errors += smb->rx_len_err;
+ adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;
+ adapter->soft_stats.rx_frame_errors += smb->rx_align_err;
+ adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov +
+ smb->rx_rxf_ov);
+
+ adapter->soft_stats.rx_pause += smb->rx_pause;
+ adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;
+ adapter->soft_stats.rx_trunc += smb->rx_sz_ov;
+
+ /* Tx Errors */
+ adapter->soft_stats.tx_errors += (smb->tx_late_col +
+ smb->tx_abort_col +
+ smb->tx_underrun + smb->tx_trunc);
+ adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;
+ adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;
+ adapter->soft_stats.tx_window_errors += smb->tx_late_col;
+
+ adapter->soft_stats.excecol += smb->tx_abort_col;
+ adapter->soft_stats.deffer += smb->tx_defer;
+ adapter->soft_stats.scc += smb->tx_1_col;
+ adapter->soft_stats.mcc += smb->tx_2_col;
+ adapter->soft_stats.latecol += smb->tx_late_col;
+ adapter->soft_stats.tx_underun += smb->tx_underrun;
+ adapter->soft_stats.tx_trunc += smb->tx_trunc;
+ adapter->soft_stats.tx_pause += smb->tx_pause;
+
+ adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
+ adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
+ adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
+ adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
+ adapter->net_stats.multicast = adapter->soft_stats.multicast;
+ adapter->net_stats.collisions = adapter->soft_stats.collisions;
+ adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
+ adapter->net_stats.rx_over_errors =
+ adapter->soft_stats.rx_missed_errors;
+ adapter->net_stats.rx_length_errors =
+ adapter->soft_stats.rx_length_errors;
+ adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
+ adapter->net_stats.rx_frame_errors =
+ adapter->soft_stats.rx_frame_errors;
+ adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
+ adapter->net_stats.rx_missed_errors =
+ adapter->soft_stats.rx_missed_errors;
+ adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
+ adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
+ adapter->net_stats.tx_aborted_errors =
+ adapter->soft_stats.tx_aborted_errors;
+ adapter->net_stats.tx_window_errors =
+ adapter->soft_stats.tx_window_errors;
+ adapter->net_stats.tx_carrier_errors =
+ adapter->soft_stats.tx_carrier_errors;
+}
+
+static void atl1_rx_checksum(struct atl1_adapter *adapter,
+ struct rx_return_desc *rrd,
+ struct sk_buff *skb)
+{
+ skb->ip_summed = CHECKSUM_NONE;
+
+ if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+ if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC |
+ ERR_FLAG_CODE | ERR_FLAG_OV)) {
+ adapter->hw_csum_err++;
+ printk(KERN_DEBUG "%s: rx checksum error\n",
+ atl1_driver_name);
+ return;
+ }
+ }
+
+ /* not IPv4 */
+ if (!(rrd->pkt_flg & PACKET_FLAG_IPV4))
+ /* checksum is invalid, but it's not an IPv4 pkt, so ok */
+ return;
+
+ /* IPv4 packet */
+ if (likely(!(rrd->err_flg &
+ (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ adapter->hw_csum_good++;
+ return;
+ }
+
+ /* IPv4, but hardware thinks its checksum is wrong */
+ printk(KERN_DEBUG "%s: hw csum wrong pkt_flag:%x, err_flag:%x\n",
+ atl1_driver_name, rrd->pkt_flg, rrd->err_flg);
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum);
+ adapter->hw_csum_err++;
+ return;
+}
+
+/*
+ * atl1_alloc_rx_buffers - Replace used receive buffers
+ * @adapter: address of board private structure
+ */
+static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
+{
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ struct page *page;
+ unsigned long offset;
+ struct atl1_buffer *buffer_info, *next_info;
+ struct sk_buff *skb;
+ u16 num_alloc = 0;
+ u16 rfd_next_to_use, next_next;
+ struct rx_free_desc *rfd_desc;
+
+ next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use);
+ if (++next_next == rfd_ring->count)
+ next_next = 0;
+ buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+ next_info = &rfd_ring->buffer_info[next_next];
+
+ while (!buffer_info->alloced && !next_info->alloced) {
+ if (buffer_info->skb) {
+ buffer_info->alloced = 1;
+ goto next;
+ }
+
+ rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use);
+
+ skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+ if (unlikely(!skb)) { /* Better luck next round */
+ adapter->net_stats.rx_dropped++;
+ break;
+ }
+
+ /*
+ * Make buffer alignment 2 beyond a 16 byte boundary
+ * this will result in a 16 byte aligned IP header after
+ * the 14 byte MAC header is removed
+ */
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb->dev = netdev;
+
+ buffer_info->alloced = 1;
+ buffer_info->skb = skb;
+ buffer_info->length = (u16) adapter->rx_buffer_len;
+ page = virt_to_page(skb->data);
+ offset = (unsigned long)skb->data & ~PAGE_MASK;
+ buffer_info->dma = pci_map_page(pdev, page, offset,
+ adapter->rx_buffer_len,
+ PCI_DMA_FROMDEVICE);
+ rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+ rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len);
+ rfd_desc->coalese = 0;
+
+next:
+ rfd_next_to_use = next_next;
+ if (unlikely(++next_next == rfd_ring->count))
+ next_next = 0;
+
+ buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+ next_info = &rfd_ring->buffer_info[next_next];
+ num_alloc++;
+ }
+
+ if (num_alloc) {
+ /*
+ * Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64).
+ */
+ wmb();
+ atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use);
+ }
+ return num_alloc;
+}
+
+static void atl1_intr_rx(struct atl1_adapter *adapter)
+{
+ int i, count;
+ u16 length;
+ u16 rrd_next_to_clean;
+ u32 value;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_buffer *buffer_info;
+ struct rx_return_desc *rrd;
+ struct sk_buff *skb;
+
+ count = 0;
+
+ rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean);
+
+ while (1) {
+ rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean);
+ i = 1;
+ if (likely(rrd->xsz.valid)) { /* packet valid */
+chk_rrd:
+ /* check rrd status */
+ if (likely(rrd->num_buf == 1))
+ goto rrd_ok;
+
+ /* rrd seems to be bad */
+ if (unlikely(i-- > 0)) {
+ /* rrd may not be DMAed completely */
+ printk(KERN_DEBUG
+ "%s: RRD may not be DMAed completely\n",
+ atl1_driver_name);
+ udelay(1);
+ goto chk_rrd;
+ }
+ /* bad rrd */
+ printk(KERN_DEBUG "%s: bad RRD\n", atl1_driver_name);
+ /* see if update RFD index */
+ if (rrd->num_buf > 1) {
+ u16 num_buf;
+ num_buf =
+ (rrd->xsz.xsum_sz.pkt_size +
+ adapter->rx_buffer_len -
+ 1) / adapter->rx_buffer_len;
+ if (rrd->num_buf == num_buf) {
+ /* clean alloc flag for bad rrd */
+ while (rfd_ring->next_to_clean !=
+ (rrd->buf_indx + num_buf)) {
+ rfd_ring->buffer_info[rfd_ring->
+ next_to_clean].alloced = 0;
+ if (++rfd_ring->next_to_clean ==
+ rfd_ring->count) {
+ rfd_ring->
+ next_to_clean = 0;
+ }
+ }
+ }
+ }
+
+ /* update rrd */
+ rrd->xsz.valid = 0;
+ if (++rrd_next_to_clean == rrd_ring->count)
+ rrd_next_to_clean = 0;
+ count++;
+ continue;
+ } else { /* current rrd still not be updated */
+
+ break;
+ }
+rrd_ok:
+ /* clean alloc flag for bad rrd */
+ while (rfd_ring->next_to_clean != rrd->buf_indx) {
+ rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced =
+ 0;
+ if (++rfd_ring->next_to_clean == rfd_ring->count)
+ rfd_ring->next_to_clean = 0;
+ }
+
+ buffer_info = &rfd_ring->buffer_info[rrd->buf_indx];
+ if (++rfd_ring->next_to_clean == rfd_ring->count)
+ rfd_ring->next_to_clean = 0;
+
+ /* update rrd next to clean */
+ if (++rrd_next_to_clean == rrd_ring->count)
+ rrd_next_to_clean = 0;
+ count++;
+
+ if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) {
+ if (!(rrd->err_flg &
+ (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM
+ | ERR_FLAG_LEN))) {
+ /* packet error, don't need upstream */
+ buffer_info->alloced = 0;
+ rrd->xsz.valid = 0;
+ continue;
+ }
+ }
+
+ /* Good Receive */
+ pci_unmap_page(adapter->pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_FROMDEVICE);
+ skb = buffer_info->skb;
+ length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size);
+
+ skb_put(skb, length - ETHERNET_FCS_SIZE);
+
+ /* Receive Checksum Offload */
+ atl1_rx_checksum(adapter, rrd, skb);
+ skb->protocol = eth_type_trans(skb, adapter->netdev);
+
+ if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) {
+ u16 vlan_tag = (rrd->vlan_tag >> 4) |
+ ((rrd->vlan_tag & 7) << 13) |
+ ((rrd->vlan_tag & 8) << 9);
+ vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag);
+ } else
+ netif_rx(skb);
+
+ /* let protocol layer free skb */
+ buffer_info->skb = NULL;
+ buffer_info->alloced = 0;
+ rrd->xsz.valid = 0;
+
+ adapter->netdev->last_rx = jiffies;
+ }
+
+ atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
+
+ atl1_alloc_rx_buffers(adapter);
+
+ /* update mailbox ? */
+ if (count) {
+ u32 tpd_next_to_use;
+ u32 rfd_next_to_use;
+ u32 rrd_next_to_clean;
+
+ spin_lock(&adapter->mb_lock);
+
+ tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+ rfd_next_to_use =
+ atomic_read(&adapter->rfd_ring.next_to_use);
+ rrd_next_to_clean =
+ atomic_read(&adapter->rrd_ring.next_to_clean);
+ value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+ MB_RFD_PROD_INDX_SHIFT) |
+ ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+ MB_RRD_CONS_INDX_SHIFT) |
+ ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+ MB_TPD_PROD_INDX_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+ spin_unlock(&adapter->mb_lock);
+ }
+}
+
+static void atl1_intr_tx(struct atl1_adapter *adapter)
+{
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_buffer *buffer_info;
+ u16 sw_tpd_next_to_clean;
+ u16 cmb_tpd_next_to_clean;
+ u8 update = 0;
+
+ sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+ cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
+
+ while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
+ struct tx_packet_desc *tpd;
+ update = 1;
+ tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
+ buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
+ if (buffer_info->dma) {
+ pci_unmap_page(adapter->pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_TODEVICE);
+ buffer_info->dma = 0;
+ }
+
+ if (buffer_info->skb) {
+ dev_kfree_skb_irq(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+ tpd->buffer_addr = 0;
+ tpd->desc.data = 0;
+
+ if (++sw_tpd_next_to_clean == tpd_ring->count)
+ sw_tpd_next_to_clean = 0;
+ }
+ atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean);
+
+ if (netif_queue_stopped(adapter->netdev)
+ && netif_carrier_ok(adapter->netdev))
+ netif_wake_queue(adapter->netdev);
+}
+
+static void atl1_check_for_link(struct atl1_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ u16 phy_data = 0;
+
+ spin_lock(&adapter->lock);
+ adapter->phy_timer_pending = false;
+ atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+ spin_unlock(&adapter->lock);
+
+ /* notify upper layer link down ASAP */
+ if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */
+ if (netif_carrier_ok(netdev)) { /* old link state: Up */
+ printk(KERN_INFO "%s: %s link is down\n",
+ atl1_driver_name, netdev->name);
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ }
+ schedule_work(&adapter->link_chg_task);
+}
+
+/*
+ * atl1_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl1_intr(int irq, void *data)
+{
+ /*struct atl1_adapter *adapter = ((struct net_device *)data)->priv;*/
+ struct atl1_adapter *adapter = netdev_priv(data);
+ u32 status;
+ u8 update_rx;
+ int max_ints = 10;
+
+ status = adapter->cmb.cmb->int_stats;
+ if (!status)
+ return IRQ_NONE;
+
+ update_rx = 0;
+
+ do {
+ /* clear CMB interrupt status at once */
+ adapter->cmb.cmb->int_stats = 0;
+
+ if (status & ISR_GPHY) /* clear phy status */
+ atl1_clear_phy_int(adapter);
+
+ /* clear ISR status, and Enable CMB DMA/Disable Interrupt */
+ iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR);
+
+ /* check if SMB intr */
+ if (status & ISR_SMB)
+ atl1_inc_smb(adapter);
+
+ /* check if PCIE PHY Link down */
+ if (status & ISR_PHY_LINKDOWN) {
+ printk(KERN_DEBUG "%s: pcie phy link down %x\n",
+ atl1_driver_name, status);
+ if (netif_running(adapter->netdev)) { /* reset MAC */
+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+ schedule_work(&adapter->pcie_dma_to_rst_task);
+ return IRQ_HANDLED;
+ }
+ }
+
+ /* check if DMA read/write error ? */
+ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+ printk(KERN_DEBUG
+ "%s: pcie DMA r/w error (status = 0x%x)\n",
+ atl1_driver_name, status);
+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+ schedule_work(&adapter->pcie_dma_to_rst_task);
+ return IRQ_HANDLED;
+ }
+
+ /* link event */
+ if (status & ISR_GPHY) {
+ adapter->soft_stats.tx_carrier_errors++;
+ atl1_check_for_link(adapter);
+ }
+
+ /* transmit event */
+ if (status & ISR_CMB_TX)
+ atl1_intr_tx(adapter);
+
+ /* rx exception */
+ if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
+ ISR_RRD_OV | ISR_HOST_RFD_UNRUN |
+ ISR_HOST_RRD_OV | ISR_CMB_RX))) {
+ if (status &
+ (ISR_RXF_OV | ISR_RFD_UNRUN | ISR_RRD_OV |
+ ISR_HOST_RFD_UNRUN | ISR_HOST_RRD_OV))
+ printk(KERN_INFO
+ "%s: rx exception: status = 0x%x\n",
+ atl1_driver_name, status);
+ atl1_intr_rx(adapter);
+ }
+
+ if (--max_ints < 0)
+ break;
+
+ } while ((status = adapter->cmb.cmb->int_stats));
+
+ /* re-enable Interrupt */
+ iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);
+ return IRQ_HANDLED;
+}
+
+/*
+ * atl1_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated. This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1_set_multi(struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+ struct dev_mc_list *mc_ptr;
+ u32 rctl;
+ u32 hash_value;
+
+ /* Check for Promiscuous and All Multicast modes */
+ rctl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+ if (netdev->flags & IFF_PROMISC)
+ rctl |= MAC_CTRL_PROMIS_EN;
+ else if (netdev->flags & IFF_ALLMULTI) {
+ rctl |= MAC_CTRL_MC_ALL_EN;
+ rctl &= ~MAC_CTRL_PROMIS_EN;
+ } else
+ rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+
+ iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL);
+
+ /* clear the old settings from the multicast hash table */
+ iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE);
+ iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2));
+
+ /* compute mc addresses' hash value ,and put it into hash table */
+ for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+ hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr);
+ atl1_hash_set(hw, hash_value);
+ }
+}
+
+static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter)
+{
+ u32 value;
+ struct atl1_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ /* Config MAC CTRL Register */
+ value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+ /* duplex */
+ if (FULL_DUPLEX == adapter->link_duplex)
+ value |= MAC_CTRL_DUPLX;
+ /* speed */
+ value |= ((u32) ((SPEED_1000 == adapter->link_speed) ?
+ MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+ MAC_CTRL_SPEED_SHIFT);
+ /* flow control */
+ value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+ /* PAD & CRC */
+ value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+ /* preamble length */
+ value |= (((u32) adapter->hw.preamble_len
+ & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+ /* vlan */
+ if (adapter->vlgrp)
+ value |= MAC_CTRL_RMV_VLAN;
+ /* rx checksum
+ if (adapter->rx_csum)
+ value |= MAC_CTRL_RX_CHKSUM_EN;
+ */
+ /* filter mode */
+ value |= MAC_CTRL_BC_EN;
+ if (netdev->flags & IFF_PROMISC)
+ value |= MAC_CTRL_PROMIS_EN;
+ else if (netdev->flags & IFF_ALLMULTI)
+ value |= MAC_CTRL_MC_ALL_EN;
+ /* value |= MAC_CTRL_LOOPBACK; */
+ iowrite32(value, hw->hw_addr + REG_MAC_CTRL);
+}
+
+static u32 atl1_check_link(struct atl1_adapter *adapter)
+{
+ struct atl1_hw *hw = &adapter->hw;
+ struct net_device *netdev = adapter->netdev;
+ u32 ret_val;
+ u16 speed, duplex, phy_data;
+ int reconfig = 0;
+
+ /* MII_BMSR must read twice */
+ atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+ atl1_read_phy_reg(hw, MII_BMSR, &phy_data);
+ if (!(phy_data & BMSR_LSTATUS)) { /* link down */
+ if (netif_carrier_ok(netdev)) { /* old link state: Up */
+ printk(KERN_INFO "%s: link is down\n",
+ atl1_driver_name);
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ return ATL1_SUCCESS;
+ }
+
+ /* Link Up */
+ ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val)
+ return ret_val;
+
+ switch (hw->media_type) {
+ case MEDIA_TYPE_1000M_FULL:
+ if (speed != SPEED_1000 || duplex != FULL_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_100M_FULL:
+ if (speed != SPEED_100 || duplex != FULL_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ if (speed != SPEED_100 || duplex != HALF_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ if (speed != SPEED_10 || duplex != FULL_DUPLEX)
+ reconfig = 1;
+ break;
+ case MEDIA_TYPE_10M_HALF:
+ if (speed != SPEED_10 || duplex != HALF_DUPLEX)
+ reconfig = 1;
+ break;
+ }
+
+ /* link result is our setting */
+ if (!reconfig) {
+ if (adapter->link_speed != speed
+ || adapter->link_duplex != duplex) {
+ adapter->link_speed = speed;
+ adapter->link_duplex = duplex;
+ atl1_setup_mac_ctrl(adapter);
+ printk(KERN_INFO "%s: %s link is up %d Mbps %s\n",
+ atl1_driver_name, netdev->name,
+ adapter->link_speed,
+ adapter->link_duplex ==
+ FULL_DUPLEX ? "full duplex" : "half duplex");
+ }
+ if (!netif_carrier_ok(netdev)) { /* Link down -> Up */
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+ return ATL1_SUCCESS;
+ }
+
+ /* change orignal link status */
+ if (netif_carrier_ok(netdev)) {
+ adapter->link_speed = SPEED_0;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+
+ if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR &&
+ hw->media_type != MEDIA_TYPE_1000M_FULL) {
+ switch (hw->media_type) {
+ case MEDIA_TYPE_100M_FULL:
+ phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 |
+ MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_100M_HALF:
+ phy_data = MII_CR_SPEED_100 | MII_CR_RESET;
+ break;
+ case MEDIA_TYPE_10M_FULL:
+ phy_data =
+ MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ default: /* MEDIA_TYPE_10M_HALF: */
+ phy_data = MII_CR_SPEED_10 | MII_CR_RESET;
+ break;
+ }
+ atl1_write_phy_reg(hw, MII_BMCR, phy_data);
+ return ATL1_SUCCESS;
+ }
+
+ /* auto-neg, insert timer to re-config phy */
+ if (!adapter->phy_timer_pending) {
+ adapter->phy_timer_pending = true;
+ mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
+ }
+
+ return ATL1_SUCCESS;
+}
+
+static void set_flow_ctrl_old(struct atl1_adapter *adapter)
+{
+ u32 hi, lo, value;
+
+ /* RFD Flow Control */
+ value = adapter->rfd_ring.count;
+ hi = value / 16;
+ if (hi < 2)
+ hi = 2;
+ lo = value * 7 / 8;
+
+ value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+ /* RRD Flow Control */
+ value = adapter->rrd_ring.count;
+ lo = value / 16;
+ hi = value * 7 / 8;
+ if (lo < 2)
+ lo = 2;
+ value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+static void set_flow_ctrl_new(struct atl1_hw *hw)
+{
+ u32 hi, lo, value;
+
+ /* RXF Flow Control */
+ value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN);
+ lo = value / 16;
+ if (lo < 192)
+ lo = 192;
+ hi = value * 7 / 8;
+ if (hi < lo)
+ hi = lo + 16;
+ value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+ ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH);
+
+ /* RRD Flow Control */
+ value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN);
+ lo = value / 8;
+ hi = value * 7 / 8;
+ if (lo < 2)
+ lo = 2;
+ if (hi < lo)
+ hi = lo + 3;
+ value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) |
+ ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH);
+}
+
+/*
+ * atl1_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static u32 atl1_configure(struct atl1_adapter *adapter)
+{
+ struct atl1_hw *hw = &adapter->hw;
+ u32 value;
+
+ /* clear interrupt status */
+ iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR);
+
+ /* set MAC Address */
+ value = (((u32) hw->mac_addr[2]) << 24) |
+ (((u32) hw->mac_addr[3]) << 16) |
+ (((u32) hw->mac_addr[4]) << 8) |
+ (((u32) hw->mac_addr[5]));
+ iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR);
+ value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1]));
+ iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4));
+
+ /* tx / rx ring */
+
+ /* HI base address */
+ iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32),
+ hw->hw_addr + REG_DESC_BASE_ADDR_HI);
+ /* LO base address */
+ iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_RFD_ADDR_LO);
+ iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_RRD_ADDR_LO);
+ iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_TPD_ADDR_LO);
+ iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_CMB_ADDR_LO);
+ iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL),
+ hw->hw_addr + REG_DESC_SMB_ADDR_LO);
+
+ /* element count */
+ value = adapter->rrd_ring.count;
+ value <<= 16;
+ value += adapter->rfd_ring.count;
+ iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE);
+ iowrite32(adapter->tpd_ring.count, hw->hw_addr + REG_DESC_TPD_RING_SIZE);
+
+ /* Load Ptr */
+ iowrite32(1, hw->hw_addr + REG_LOAD_PTR);
+
+ /* config Mailbox */
+ value = ((atomic_read(&adapter->tpd_ring.next_to_use)
+ & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) |
+ ((atomic_read(&adapter->rrd_ring.next_to_clean)
+ & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) |
+ ((atomic_read(&adapter->rfd_ring.next_to_use)
+ & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_MAILBOX);
+
+ /* config IPG/IFG */
+ value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK)
+ << MAC_IPG_IFG_IPGT_SHIFT) |
+ (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK)
+ << MAC_IPG_IFG_MIFG_SHIFT) |
+ (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK)
+ << MAC_IPG_IFG_IPGR1_SHIFT) |
+ (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK)
+ << MAC_IPG_IFG_IPGR2_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG);
+
+ /* config Half-Duplex Control */
+ value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) |
+ (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK)
+ << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) |
+ MAC_HALF_DUPLX_CTRL_EXC_DEF_EN |
+ (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) |
+ (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK)
+ << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL);
+
+ /* set Interrupt Moderator Timer */
+ iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT);
+ iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL);
+
+ /* set Interrupt Clear Timer */
+ iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);
+
+ /* set MTU, 4 : VLAN */
+ iowrite32(hw->max_frame_size + 4, hw->hw_addr + REG_MTU);
+
+ /* jumbo size & rrd retirement timer */
+ value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
+ << RXQ_JMBOSZ_TH_SHIFT) |
+ (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK)
+ << RXQ_JMBO_LKAH_SHIFT) |
+ (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK)
+ << RXQ_RRD_TIMER_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM);
+
+ /* Flow Control */
+ switch (hw->dev_rev) {
+ case 0x8001:
+ case 0x9001:
+ case 0x9002:
+ case 0x9003:
+ set_flow_ctrl_old(adapter);
+ break;
+ default:
+ set_flow_ctrl_new(hw);
+ break;
+ }
+
+ /* config TXQ */
+ value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK)
+ << TXQ_CTRL_TPD_BURST_NUM_SHIFT) |
+ (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK)
+ << TXQ_CTRL_TXF_BURST_NUM_SHIFT) |
+ (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK)
+ << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN;
+ iowrite32(value, hw->hw_addr + REG_TXQ_CTRL);
+
+ /* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */
+ value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK)
+ << TX_JUMBO_TASK_TH_SHIFT) |
+ (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK)
+ << TX_TPD_MIN_IPG_SHIFT);
+ iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG);
+
+ /* config RXQ */
+ value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK)
+ << RXQ_CTRL_RFD_BURST_NUM_SHIFT) |
+ (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK)
+ << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) |
+ (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK)
+ << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) |
+ RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
+ iowrite32(value, hw->hw_addr + REG_RXQ_CTRL);
+
+ /* config DMA Engine */
+ value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+ << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+ ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+ << DMA_CTRL_DMAR_BURST_LEN_SHIFT) |
+ DMA_CTRL_DMAR_EN | DMA_CTRL_DMAW_EN;
+ value |= (u32) hw->dma_ord;
+ if (atl1_rcb_128 == hw->rcb_value)
+ value |= DMA_CTRL_RCB_VALUE;
+ iowrite32(value, hw->hw_addr + REG_DMA_CTRL);
+
+ /* config CMB / SMB */
+ value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16);
+ iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH);
+ value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16);
+ iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER);
+ iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER);
+
+ /* --- enable CMB / SMB */
+ value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN;
+ iowrite32(value, hw->hw_addr + REG_CSMB_CTRL);
+
+ value = ioread32(adapter->hw.hw_addr + REG_ISR);
+ if (unlikely((value & ISR_PHY_LINKDOWN) != 0))
+ value = 1; /* config failed */
+ else
+ value = 0;
+
+ /* clear all interrupt status */
+ iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR);
+ iowrite32(0, adapter->hw.hw_addr + REG_ISR);
+ return value;
+}
+
+/*
+ * atl1_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static void atl1_irq_disable(struct atl1_adapter *adapter)
+{
+ atomic_inc(&adapter->irq_sem);
+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+ ioread32(adapter->hw.hw_addr + REG_IMR);
+ synchronize_irq(adapter->pdev->irq);
+}
+
+static void atl1_vlan_rx_register(struct net_device *netdev,
+ struct vlan_group *grp)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ unsigned long flags;
+ u32 ctrl;
+
+ spin_lock_irqsave(&adapter->lock, flags);
+ /* atl1_irq_disable(adapter); */
+ adapter->vlgrp = grp;
+
+ if (grp) {
+ /* enable VLAN tag insert/strip */
+ ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+ ctrl |= MAC_CTRL_RMV_VLAN;
+ iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+ } else {
+ /* disable VLAN tag insert/strip */
+ ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);
+ ctrl &= ~MAC_CTRL_RMV_VLAN;
+ iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);
+ }
+
+ /* atl1_irq_enable(adapter); */
+ spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+/* FIXME: justify or remove -- CHS */
+static void atl1_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+ /* We don't do Vlan filtering */
+ return;
+}
+
+/* FIXME: this looks wrong too -- CHS */
+static void atl1_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->lock, flags);
+ /* atl1_irq_disable(adapter); */
+ if (adapter->vlgrp)
+ adapter->vlgrp->vlan_devices[vid] = NULL;
+ /* atl1_irq_enable(adapter); */
+ spin_unlock_irqrestore(&adapter->lock, flags);
+ /* We don't do Vlan filtering */
+ return;
+}
+
+static void atl1_restore_vlan(struct atl1_adapter *adapter)
+{
+ atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ if (adapter->vlgrp) {
+ u16 vid;
+ for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ if (!adapter->vlgrp->vlan_devices[vid])
+ continue;
+ atl1_vlan_rx_add_vid(adapter->netdev, vid);
+ }
+ }
+}
+
+static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring)
+{
+ u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+ u16 next_to_use = atomic_read(&tpd_ring->next_to_use);
+ return ((next_to_clean >
+ next_to_use) ? next_to_clean - next_to_use -
+ 1 : tpd_ring->count + next_to_clean - next_to_use - 1);
+}
+
+static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
+ struct tso_param *tso)
+{
+ /* We enter this function holding a spinlock. */
+ u8 ipofst;
+ int err;
+
+ if (skb_shinfo(skb)->gso_size) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (unlikely(err))
+ return err;
+ }
+
+ if (skb->protocol == ntohs(ETH_P_IP)) {
+ skb->nh.iph->tot_len = 0;
+ skb->nh.iph->check = 0;
+ skb->h.th->check =
+ ~csum_tcpudp_magic(skb->nh.iph->saddr,
+ skb->nh.iph->daddr, 0,
+ IPPROTO_TCP, 0);
+ ipofst = skb->nh.raw - skb->data;
+ if (ipofst != ENET_HEADER_SIZE) /* 802.3 frame */
+ tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT;
+
+ tso->tsopl |= (skb->nh.iph->ihl &
+ CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT;
+ tso->tsopl |= ((skb->h.th->doff << 2) &
+ TSO_PARAM_TCPHDRLEN_MASK) << TSO_PARAM_TCPHDRLEN_SHIFT;
+ tso->tsopl |= (skb_shinfo(skb)->gso_size &
+ TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT;
+ tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT;
+ tso->tsopl |= 1 << TSO_PARAM_TCPCKSUM_SHIFT;
+ tso->tsopl |= 1 << TSO_PARAM_SEGMENT_SHIFT;
+ return true;
+ }
+ }
+ return false;
+}
+
+static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb,
+ struct csum_param *csum)
+{
+ u8 css, cso;
+
+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+ cso = skb->h.raw - skb->data;
+ css = (skb->h.raw + skb->csum) - skb->data;
+ if (unlikely(cso & 0x1)) {
+ printk(KERN_DEBUG "%s: payload offset != even number\n",
+ atl1_driver_name);
+ return -1;
+ }
+ csum->csumpl |= (cso & CSUM_PARAM_PLOADOFFSET_MASK) <<
+ CSUM_PARAM_PLOADOFFSET_SHIFT;
+ csum->csumpl |= (css & CSUM_PARAM_XSUMOFFSET_MASK) <<
+ CSUM_PARAM_XSUMOFFSET_SHIFT;
+ csum->csumpl |= 1 << CSUM_PARAM_CUSTOMCKSUM_SHIFT;
+ return true;
+ }
+
+ return true;
+}
+
+static void atl1_tx_map(struct atl1_adapter *adapter,
+ struct sk_buff *skb, bool tcp_seg)
+{
+ /* We enter this function holding a spinlock. */
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_buffer *buffer_info;
+ struct page *page;
+ int first_buf_len = skb->len;
+ unsigned long offset;
+ unsigned int nr_frags;
+ unsigned int f;
+ u16 tpd_next_to_use;
+ u16 proto_hdr_len;
+ u16 i, m, len12;
+
+ first_buf_len -= skb->data_len;
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
+ buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+ if (unlikely(buffer_info->skb))
+ BUG();
+ buffer_info->skb = NULL; /* put skb in last TPD */
+
+ if (tcp_seg) {
+ /* TSO/GSO */
+ proto_hdr_len =
+ ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+ buffer_info->length = proto_hdr_len;
+ page = virt_to_page(skb->data);
+ offset = (unsigned long)skb->data & ~PAGE_MASK;
+ buffer_info->dma = pci_map_page(adapter->pdev, page,
+ offset, proto_hdr_len,
+ PCI_DMA_TODEVICE);
+
+ if (++tpd_next_to_use == tpd_ring->count)
+ tpd_next_to_use = 0;
+
+ if (first_buf_len > proto_hdr_len) {
+ len12 = first_buf_len - proto_hdr_len;
+ m = (len12 + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ for (i = 0; i < m; i++) {
+ buffer_info =
+ &tpd_ring->buffer_info[tpd_next_to_use];
+ buffer_info->skb = NULL;
+ buffer_info->length =
+ (MAX_TX_BUF_LEN >=
+ len12) ? MAX_TX_BUF_LEN : len12;
+ len12 -= buffer_info->length;
+ page = virt_to_page(skb->data +
+ (proto_hdr_len +
+ i * MAX_TX_BUF_LEN));
+ offset = (unsigned long)(skb->data +
+ (proto_hdr_len +
+ i * MAX_TX_BUF_LEN)) &
+ ~PAGE_MASK;
+ buffer_info->dma =
+ pci_map_page(adapter->pdev, page, offset,
+ buffer_info->length,
+ PCI_DMA_TODEVICE);
+ if (++tpd_next_to_use == tpd_ring->count)
+ tpd_next_to_use = 0;
+ }
+ }
+ } else {
+ /* not TSO/GSO */
+ buffer_info->length = first_buf_len;
+ page = virt_to_page(skb->data);
+ offset = (unsigned long)skb->data & ~PAGE_MASK;
+ buffer_info->dma = pci_map_page(adapter->pdev, page,
+ offset, first_buf_len,
+ PCI_DMA_TODEVICE);
+ if (++tpd_next_to_use == tpd_ring->count)
+ tpd_next_to_use = 0;
+ }
+
+ for (f = 0; f < nr_frags; f++) {
+ struct skb_frag_struct *frag;
+ u16 lenf, i, m;
+
+ frag = &skb_shinfo(skb)->frags[f];
+ lenf = frag->size;
+
+ m = (lenf + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ for (i = 0; i < m; i++) {
+ buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+ if (unlikely(buffer_info->skb))
+ BUG();
+ buffer_info->skb = NULL;
+ buffer_info->length =
+ (lenf > MAX_TX_BUF_LEN) ? MAX_TX_BUF_LEN : lenf;
+ lenf -= buffer_info->length;
+ buffer_info->dma =
+ pci_map_page(adapter->pdev, frag->page,
+ frag->page_offset + i * MAX_TX_BUF_LEN,
+ buffer_info->length, PCI_DMA_TODEVICE);
+
+ if (++tpd_next_to_use == tpd_ring->count)
+ tpd_next_to_use = 0;
+ }
+ }
+
+ /* last tpd's buffer-info */
+ buffer_info->skb = skb;
+}
+
+static void atl1_tx_queue(struct atl1_adapter *adapter, int count,
+ union tpd_descr *descr)
+{
+ /* We enter this function holding a spinlock. */
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ int j;
+ u32 val;
+ struct atl1_buffer *buffer_info;
+ struct tx_packet_desc *tpd;
+ u16 tpd_next_to_use = atomic_read(&tpd_ring->next_to_use);
+
+ for (j = 0; j < count; j++) {
+ buffer_info = &tpd_ring->buffer_info[tpd_next_to_use];
+ tpd = ATL1_TPD_DESC(&adapter->tpd_ring, tpd_next_to_use);
+ tpd->desc.csum.csumpu = descr->csum.csumpu;
+ tpd->desc.csum.csumpl = descr->csum.csumpl;
+ tpd->desc.tso.tsopu = descr->tso.tsopu;
+ tpd->desc.tso.tsopl = descr->tso.tsopl;
+ tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+ tpd->desc.data = descr->data;
+ tpd->desc.csum.csumpu |= (cpu_to_le16(buffer_info->length) &
+ CSUM_PARAM_BUFLEN_MASK) << CSUM_PARAM_BUFLEN_SHIFT;
+
+ val = (descr->tso.tsopl >> TSO_PARAM_SEGMENT_SHIFT) &
+ TSO_PARAM_SEGMENT_MASK;
+ if (val && !j)
+ tpd->desc.tso.tsopl |= 1 << TSO_PARAM_HDRFLAG_SHIFT;
+
+ if (j == (count - 1))
+ tpd->desc.csum.csumpl |= 1 << CSUM_PARAM_EOP_SHIFT;
+
+ if (++tpd_next_to_use == tpd_ring->count)
+ tpd_next_to_use = 0;
+ }
+ /*
+ * Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64).
+ */
+ wmb();
+
+ atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use);
+}
+
+static void atl1_update_mailbox(struct atl1_adapter *adapter)
+{
+ unsigned long flags;
+ u32 tpd_next_to_use;
+ u32 rfd_next_to_use;
+ u32 rrd_next_to_clean;
+ u32 value;
+
+ spin_lock_irqsave(&adapter->mb_lock, flags);
+
+ tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use);
+ rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use);
+ rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean);
+
+ value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) <<
+ MB_RFD_PROD_INDX_SHIFT) |
+ ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) <<
+ MB_RRD_CONS_INDX_SHIFT) |
+ ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) <<
+ MB_TPD_PROD_INDX_SHIFT);
+ iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX);
+
+ spin_unlock_irqrestore(&adapter->mb_lock, flags);
+}
+
+static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ int len = skb->len;
+ int tso;
+ int count = 1;
+ int ret_val;
+ u32 val;
+ union tpd_descr param;
+ u16 frag_size;
+ u16 vlan_tag;
+ unsigned long flags;
+ unsigned int nr_frags = 0;
+ unsigned int mss = 0;
+ unsigned int f;
+ unsigned int proto_hdr_len;
+
+ len -= skb->data_len;
+
+ if (unlikely(skb->len == 0)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ param.data = 0;
+ param.tso.tsopu = 0;
+ param.tso.tsopl = 0;
+ param.csum.csumpu = 0;
+ param.csum.csumpl = 0;
+
+ /* nr_frags will be nonzero if we're doing scatter/gather (SG) */
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ for (f = 0; f < nr_frags; f++) {
+ frag_size = skb_shinfo(skb)->frags[f].size;
+ if (frag_size)
+ count +=
+ (frag_size + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ }
+
+ /* mss will be nonzero if we're doing segment offload (TSO/GSO) */
+ mss = skb_shinfo(skb)->gso_size;
+ if (mss) {
+ if (skb->protocol == ntohs(ETH_P_IP)) {
+ proto_hdr_len = ((skb->h.raw - skb->data) +
+ (skb->h.th->doff << 2));
+ if (unlikely(proto_hdr_len > len)) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ /* need additional TPD ? */
+ if (proto_hdr_len != len)
+ count += (len - proto_hdr_len +
+ MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+ }
+ }
+
+ local_irq_save(flags);
+ if (!spin_trylock(&adapter->lock)) {
+ /* Can't get lock - tell upper layer to requeue */
+ local_irq_restore(flags);
+ printk(KERN_DEBUG "%s: TX locked\n", atl1_driver_name);
+ return NETDEV_TX_LOCKED;
+ }
+
+ if (tpd_avail(&adapter->tpd_ring) < count) {
+ /* not enough descriptors */
+ netif_stop_queue(netdev);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+ printk(KERN_DEBUG "%s: TX busy\n", atl1_driver_name);
+ return NETDEV_TX_BUSY;
+ }
+
+ param.data = 0;
+
+ if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ vlan_tag = vlan_tx_tag_get(skb);
+ vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) |
+ ((vlan_tag >> 9) & 0x8);
+ param.csum.csumpl |= 1 << CSUM_PARAM_INSVLAG_SHIFT;
+ param.csum.csumpu |= (vlan_tag & CSUM_PARAM_VALANTAG_MASK) <<
+ CSUM_PARAM_VALAN_SHIFT;
+ }
+
+ tso = atl1_tso(adapter, skb, &param.tso);
+ if (tso < 0) {
+ spin_unlock_irqrestore(&adapter->lock, flags);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (!tso) {
+ ret_val = atl1_tx_csum(adapter, skb, &param.csum);
+ if (ret_val < 0) {
+ spin_unlock_irqrestore(&adapter->lock, flags);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ }
+
+ val = (param.csum.csumpl >> CSUM_PARAM_SEGMENT_SHIFT) &
+ CSUM_PARAM_SEGMENT_MASK;
+ atl1_tx_map(adapter, skb, 1 == val);
+ atl1_tx_queue(adapter, count, &param);
+ netdev->trans_start = jiffies;
+ spin_unlock_irqrestore(&adapter->lock, flags);
+ atl1_update_mailbox(adapter);
+ return NETDEV_TX_OK;
+}
+
+/*
+ * atl1_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1_get_stats(struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ return &adapter->net_stats;
+}
+
+/*
+ * atl1_clean_rx_ring - Free RFD Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_rx_ring(struct atl1_adapter *adapter)
+{
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_buffer *buffer_info;
+ struct pci_dev *pdev = adapter->pdev;
+ unsigned long size;
+ unsigned int i;
+
+ /* Free all the Rx ring sk_buffs */
+ for (i = 0; i < rfd_ring->count; i++) {
+ buffer_info = &rfd_ring->buffer_info[i];
+ if (buffer_info->dma) {
+ pci_unmap_page(pdev,
+ buffer_info->dma,
+ buffer_info->length,
+ PCI_DMA_FROMDEVICE);
+ buffer_info->dma = 0;
+ }
+ if (buffer_info->skb) {
+ dev_kfree_skb(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+ }
+
+ size = sizeof(struct atl1_buffer) * rfd_ring->count;
+ memset(rfd_ring->buffer_info, 0, size);
+
+ /* Zero out the descriptor ring */
+ memset(rfd_ring->desc, 0, rfd_ring->size);
+
+ rfd_ring->next_to_clean = 0;
+ atomic_set(&rfd_ring->next_to_use, 0);
+
+ rrd_ring->next_to_use = 0;
+ atomic_set(&rrd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ */
+static void atl1_clean_tx_ring(struct atl1_adapter *adapter)
+{
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_buffer *buffer_info;
+ struct pci_dev *pdev = adapter->pdev;
+ unsigned long size;
+ unsigned int i;
+
+ /* Free all the Tx ring sk_buffs */
+ for (i = 0; i < tpd_ring->count; i++) {
+ buffer_info = &tpd_ring->buffer_info[i];
+ if (buffer_info->dma) {
+ pci_unmap_page(pdev, buffer_info->dma,
+ buffer_info->length, PCI_DMA_TODEVICE);
+ buffer_info->dma = 0;
+ }
+ }
+
+ for (i = 0; i < tpd_ring->count; i++) {
+ buffer_info = &tpd_ring->buffer_info[i];
+ if (buffer_info->skb) {
+ dev_kfree_skb_any(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+ }
+
+ size = sizeof(struct atl1_buffer) * tpd_ring->count;
+ memset(tpd_ring->buffer_info, 0, size);
+
+ /* Zero out the descriptor ring */
+ memset(tpd_ring->desc, 0, tpd_ring->size);
+
+ atomic_set(&tpd_ring->next_to_use, 0);
+ atomic_set(&tpd_ring->next_to_clean, 0);
+}
+
+/*
+ * atl1_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+void atl1_free_ring_resources(struct atl1_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring;
+ struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring;
+ struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring;
+ struct atl1_ring_header *ring_header = &adapter->ring_header;
+
+ atl1_clean_tx_ring(adapter);
+ atl1_clean_rx_ring(adapter);
+
+ kfree(tpd_ring->buffer_info);
+ pci_free_consistent(pdev, ring_header->size, ring_header->desc,
+ ring_header->dma);
+
+ tpd_ring->buffer_info = NULL;
+ tpd_ring->desc = NULL;
+ tpd_ring->dma = 0;
+
+ rfd_ring->buffer_info = NULL;
+ rfd_ring->desc = NULL;
+ rfd_ring->dma = 0;
+
+ rrd_ring->desc = NULL;
+ rrd_ring->dma = 0;
+}
+
+s32 atl1_up(struct atl1_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err;
+ int irq_flags = IRQF_SAMPLE_RANDOM;
+
+ /* hardware has been reset, we need to reload some things */
+ atl1_set_multi(netdev);
+ atl1_restore_vlan(adapter);
+ err = atl1_alloc_rx_buffers(adapter);
+ if (unlikely(!err)) /* no RX BUFFER allocated */
+ return -ENOMEM;
+
+ if (unlikely(atl1_configure(adapter))) {
+ err = -EIO;
+ goto err_up;
+ }
+
+ err = pci_enable_msi(adapter->pdev);
+ if (err) {
+ dev_info(&adapter->pdev->dev,
+ "Unable to enable MSI: %d\n", err);
+ irq_flags |= IRQF_SHARED;
+ }
+
+ err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,
+ netdev->name, netdev);
+ if (unlikely(err))
+ goto err_up;
+
+ mod_timer(&adapter->watchdog_timer, jiffies);
+ atl1_irq_enable(adapter);
+ atl1_check_link(adapter);
+ return 0;
+
+ /* FIXME: unreachable code! -- CHS */
+ /* free irq disable any interrupt */
+ iowrite32(0, adapter->hw.hw_addr + REG_IMR);
+ free_irq(adapter->pdev->irq, netdev);
+
+err_up:
+ pci_disable_msi(adapter->pdev);
+ /* free rx_buffers */
+ atl1_clean_rx_ring(adapter);
+ return err;
+}
+
+void atl1_down(struct atl1_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ del_timer_sync(&adapter->watchdog_timer);
+ del_timer_sync(&adapter->phy_config_timer);
+ adapter->phy_timer_pending = false;
+
+ atl1_irq_disable(adapter);
+ free_irq(adapter->pdev->irq, netdev);
+ pci_disable_msi(adapter->pdev);
+ atl1_reset_hw(&adapter->hw);
+ adapter->cmb.cmb->int_stats = 0;
+
+ adapter->link_speed = SPEED_0;
+ adapter->link_duplex = -1;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ atl1_clean_tx_ring(adapter);
+ atl1_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ int old_mtu = netdev->mtu;
+ int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+
+ if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ printk(KERN_WARNING "%s: invalid MTU setting\n",
+ atl1_driver_name);
+ return -EINVAL;
+ }
+
+ adapter->hw.max_frame_size = max_frame;
+ adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3;
+ adapter->rx_buffer_len = (max_frame + 7) & ~7;
+ adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8;
+
+ netdev->mtu = new_mtu;
+ if ((old_mtu != new_mtu) && netif_running(netdev)) {
+ atl1_down(adapter);
+ atl1_up(adapter);
+ }
+
+ return 0;
+}
+
+/*
+ * atl1_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1_set_mac(struct net_device *netdev, void *p)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct sockaddr *addr = p;
+
+ if (netif_running(netdev))
+ return -EBUSY;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+ atl1_set_mac_addr(&adapter->hw);
+ return 0;
+}
+
+/*
+ * atl1_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_watchdog(unsigned long data)
+{
+ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+
+ /* Reset the timer */
+ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
+static int mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ u16 result;
+
+ atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result);
+
+ return result;
+}
+
+static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, int val)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+
+ atl1_write_phy_reg(&adapter->hw, reg_num, val);
+}
+
+/*
+ * atl1_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ unsigned long flags;
+ int retval;
+
+ if (!netif_running(netdev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&adapter->lock, flags);
+ retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+
+ return retval;
+}
+
+/*
+ * atl1_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+ return atl1_mii_ioctl(netdev, ifr, cmd);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/*
+ * atl1_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1_tx_timeout(struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ /* Do the reset outside of interrupt context */
+ schedule_work(&adapter->tx_timeout_task);
+}
+
+/*
+ * atl1_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1_phy_config(unsigned long data)
+{
+ struct atl1_adapter *adapter = (struct atl1_adapter *)data;
+ struct atl1_hw *hw = &adapter->hw;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->lock, flags);
+ adapter->phy_timer_pending = false;
+ atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+ atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);
+ atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+int atl1_reset(struct atl1_adapter *adapter)
+{
+ int ret;
+
+ ret = atl1_reset_hw(&adapter->hw);
+ if (ret != ATL1_SUCCESS)
+ return ret;
+ return atl1_init_hw(&adapter->hw);
+}
+
+/*
+ * atl1_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP). At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1_open(struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ int err;
+
+ /* allocate transmit descriptors */
+ err = atl1_setup_ring_resources(adapter);
+ if (err)
+ return err;
+
+ err = atl1_up(adapter);
+ if (err)
+ goto err_up;
+
+ return 0;
+
+err_up:
+ atl1_reset(adapter);
+ return err;
+}
+
+/*
+ * atl1_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static int atl1_close(struct net_device *netdev)
+{
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ atl1_down(adapter);
+ atl1_free_ring_resources(adapter);
+ return 0;
+}
+
+/*
+ * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT
+ * will assert. We do soft reset <0x1400=1> according
+ * with the SPEC. BUT, it seemes that PCIE or DMA
+ * state-machine will not be reset. DMAR_TO_INT will
+ * assert again and again.
+ */
+static void atl1_tx_timeout_task(struct work_struct *work)
+{
+ struct atl1_adapter *adapter =
+ container_of(work, struct atl1_adapter, tx_timeout_task);
+ struct net_device *netdev = adapter->netdev;
+
+ netif_device_detach(netdev);
+ atl1_down(adapter);
+ atl1_up(adapter);
+ netif_device_attach(netdev);
+}
+
+/*
+ * atl1_link_chg_task - deal with link change event Out of interrupt context
+ */
+static void atl1_link_chg_task(struct work_struct *work)
+{
+ struct atl1_adapter *adapter =
+ container_of(work, struct atl1_adapter, link_chg_task);
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->lock, flags);
+ atl1_check_link(adapter);
+ spin_unlock_irqrestore(&adapter->lock, flags);
+}
+
+/*
+ * atl1_pcie_patch - Patch for PCIE module
+ */
+static void atl1_pcie_patch(struct atl1_adapter *adapter)
+{
+ u32 value;
+ value = 0x6500;
+ iowrite32(value, adapter->hw.hw_addr + 0x12FC);
+ /* pcie flow control mode change */
+ value = ioread32(adapter->hw.hw_addr + 0x1008);
+ value |= 0x8000;
+ iowrite32(value, adapter->hw.hw_addr + 0x1008);
+}
+
+/*
+ * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400
+ * on PCI Command register is disable.
+ * The function enable this bit.
+ * Brackett, 2006/03/15
+ */
+static void atl1_via_workaround(struct atl1_adapter *adapter)
+{
+ unsigned long value;
+
+ value = ioread16(adapter->hw.hw_addr + PCI_COMMAND);
+ if (value & PCI_COMMAND_INTX_DISABLE)
+ value &= ~PCI_COMMAND_INTX_DISABLE;
+ iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND);
+}
+
+/*
+ * atl1_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl1_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *netdev;
+ struct atl1_adapter *adapter;
+ static int cards_found = 0;
+ bool pci_using_64 = true;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err) {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_DEBUG
+ "%s: no usable DMA configuration, aborting\n",
+ atl1_driver_name);
+ goto err_dma;
+ }
+ pci_using_64 = false;
+ }
+ /* Mark all PCI regions associated with PCI device
+ * pdev as being reserved by owner atl1_driver_name
+ */
+ err = pci_request_regions(pdev, atl1_driver_name);
+ if (err)
+ goto err_request_regions;
+
+ /* Enables bus-mastering on the device and calls
+ * pcibios_set_master to do the needed arch specific settings
+ */
+ pci_set_master(pdev);
+
+ netdev = alloc_etherdev(sizeof(struct atl1_adapter));
+ if (!netdev) {
+ err = -ENOMEM;
+ goto err_alloc_etherdev;
+ }
+ SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ pci_set_drvdata(pdev, netdev);
+ adapter = netdev_priv(netdev);
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
+ adapter->hw.back = adapter;
+
+ adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);
+ if (!adapter->hw.hw_addr) {
+ err = -EIO;
+ goto err_pci_iomap;
+ }
+ /* get device revision number */
+ adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr + (REG_MASTER_CTRL + 2));
+
+ /* set default ring resource counts */
+ adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;
+ adapter->tpd_ring.count = ATL1_DEFAULT_TPD;
+
+ adapter->mii.dev = netdev;
+ adapter->mii.mdio_read = mdio_read;
+ adapter->mii.mdio_write = mdio_write;
+ adapter->mii.phy_id_mask = 0x1f;
+ adapter->mii.reg_num_mask = 0x1f;
+
+ netdev->open = &atl1_open;
+ netdev->stop = &atl1_close;
+ netdev->hard_start_xmit = &atl1_xmit_frame;
+ netdev->get_stats = &atl1_get_stats;
+ netdev->set_multicast_list = &atl1_set_multi;
+ netdev->set_mac_address = &atl1_set_mac;
+ netdev->change_mtu = &atl1_change_mtu;
+ netdev->do_ioctl = &atl1_ioctl;
+ netdev->tx_timeout = &atl1_tx_timeout;
+ netdev->watchdog_timeo = 5 * HZ;
+ netdev->vlan_rx_register = atl1_vlan_rx_register;
+ netdev->vlan_rx_add_vid = atl1_vlan_rx_add_vid;
+ netdev->vlan_rx_kill_vid = atl1_vlan_rx_kill_vid;
+ netdev->ethtool_ops = &atl1_ethtool_ops;
+ adapter->bd_number = cards_found;
+ adapter->pci_using_64 = pci_using_64;
+
+ /* setup the private structure */
+ err = atl1_sw_init(adapter);
+ if (err)
+ goto err_common;
+
+ netdev->features = NETIF_F_HW_CSUM;
+ netdev->features |= NETIF_F_SG;
+ netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+
+ /*
+ * FIXME - Until tso performance gets fixed, disable the feature.
+ * Enable it with ethtool -K if desired.
+ */
+ /* netdev->features |= NETIF_F_TSO; */
+
+ if (pci_using_64)
+ netdev->features |= NETIF_F_HIGHDMA;
+
+ netdev->features |= NETIF_F_LLTX;
+
+ /*
+ * patch for some L1 of old version,
+ * the final version of L1 may not need these
+ * patches
+ */
+ /* atl1_pcie_patch(adapter); */
+
+ /* really reset GPHY core */
+ iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
+
+ /*
+ * reset the controller to
+ * put the device in a known good starting state
+ */
+ if (atl1_reset_hw(&adapter->hw)) {
+ err = -EIO;
+ goto err_common;
+ }
+
+ /* copy the MAC address out of the EEPROM */
+ atl1_read_mac_addr(&adapter->hw);
+ memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
+ err = -EIO;
+ goto err_common;
+ }
+
+ atl1_check_options(adapter);
+
+ /* pre-init the MAC, and setup link */
+ err = atl1_init_hw(&adapter->hw);
+ if (err) {
+ err = -EIO;
+ goto err_common;
+ }
+
+ atl1_pcie_patch(adapter);
+ /* assume we have no link for now */
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ init_timer(&adapter->watchdog_timer);
+ adapter->watchdog_timer.function = &atl1_watchdog;
+ adapter->watchdog_timer.data = (unsigned long)adapter;
+
+ init_timer(&adapter->phy_config_timer);
+ adapter->phy_config_timer.function = &atl1_phy_config;
+ adapter->phy_config_timer.data = (unsigned long)adapter;
+ adapter->phy_timer_pending = false;
+
+ INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
+
+ INIT_WORK(&adapter->link_chg_task, atl1_link_chg_task);
+
+ INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
+
+ err = register_netdev(netdev);
+ if (err)
+ goto err_common;
+
+ cards_found++;
+ atl1_via_workaround(adapter);
+ return 0;
+
+err_common:
+ pci_iounmap(pdev, adapter->hw.hw_addr);
+err_pci_iomap:
+ free_netdev(netdev);
+err_alloc_etherdev:
+ pci_release_regions(pdev);
+err_dma:
+err_request_regions:
+ pci_disable_device(pdev);
+ return err;
+}
+
+/*
+ * atl1_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device. The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void __devexit atl1_remove(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1_adapter *adapter;
+ /* Device not available. Return. */
+ if (!netdev)
+ return;
+
+ adapter = netdev_priv(netdev);
+ iowrite16(0, adapter->hw.hw_addr + REG_GPHY_ENABLE);
+ unregister_netdev(netdev);
+ pci_iounmap(pdev, adapter->hw.hw_addr);
+ pci_release_regions(pdev);
+ free_netdev(netdev);
+ pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ struct atl1_hw *hw = &adapter->hw;
+ u32 ctrl = 0;
+ u32 wufc = adapter->wol;
+
+ netif_device_detach(netdev);
+ if (netif_running(netdev))
+ atl1_down(adapter);
+
+ atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+ atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
+ if (ctrl & BMSR_LSTATUS)
+ wufc &= ~ATL1_WUFC_LNKC;
+
+ /* reduce speed to 10/100M */
+ if (wufc) {
+ atl1_phy_enter_power_saving(hw);
+ /* if resume, let driver to re- setup link */
+ hw->phy_configured = false;
+ atl1_set_mac_addr(hw);
+ atl1_set_multi(netdev);
+
+ ctrl = 0;
+ /* turn on magic packet wol */
+ if (wufc & ATL1_WUFC_MAG)
+ ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+ /* turn on Link change WOL */
+ if (wufc & ATL1_WUFC_LNKC)
+ ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
+ iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
+
+ /* turn on all-multi mode if wake on multicast is enabled */
+ ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);
+ ctrl &= ~MAC_CTRL_DBG;
+ ctrl &= ~MAC_CTRL_PROMIS_EN;
+ if (wufc & ATL1_WUFC_MC)
+ ctrl |= MAC_CTRL_MC_ALL_EN;
+ else
+ ctrl &= ~MAC_CTRL_MC_ALL_EN;
+
+ /* turn on broadcast mode if wake on-BC is enabled */
+ if (wufc & ATL1_WUFC_BC)
+ ctrl |= MAC_CTRL_BC_EN;
+ else
+ ctrl &= ~MAC_CTRL_BC_EN;
+
+ /* enable RX */
+ ctrl |= MAC_CTRL_RX_EN;
+ iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
+ pci_enable_wake(pdev, PCI_D3hot, 1);
+ pci_enable_wake(pdev, PCI_D3cold, 1); /* 4 == D3 cold */
+ } else {
+ iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */
+ }
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return 0;
+}
+
+static int atl1_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct atl1_adapter *adapter = netdev_priv(netdev);
+ u32 ret_val;
+
+ pci_set_power_state(pdev, 0);
+ pci_restore_state(pdev);
+
+ ret_val = pci_enable_device(pdev);
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
+
+ iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
+ atl1_reset(adapter);
+
+ if (netif_running(netdev))
+ atl1_up(adapter);
+ netif_device_attach(netdev);
+
+ atl1_via_workaround(adapter);
+
+ return 0;
+}
+#else
+#define atl1_suspend NULL
+#define atl1_resume NULL
+#endif
+
+static struct pci_driver atl1_driver = {
+ .name = atl1_driver_name,
+ .id_table = atl1_pci_tbl,
+ .probe = atl1_probe,
+ .remove = __devexit_p(atl1_remove),
+ /* Power Managment Hooks */
+ /* probably broken right now -- CHS */
+ .suspend = atl1_suspend,
+ .resume = atl1_resume
+};
+
+/*
+ * atl1_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl1_exit_module(void)
+{
+ pci_unregister_driver(&atl1_driver);
+}
+
+/*
+ * atl1_init_module - Driver Registration Routine
+ *
+ * atl1_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl1_init_module(void)
+{
+ printk(KERN_INFO "%s - version %s\n", atl1_driver_string, DRIVER_VERSION);
+ printk(KERN_INFO "%s\n", atl1_copyright);
+ return pci_register_driver(&atl1_driver);
+}
+
+module_init(atl1_init_module);
+module_exit(atl1_exit_module);
diff --git a/drivers/net/atl1/atl1_param.c b/drivers/net/atl1/atl1_param.c
new file mode 100644
index 000000000000..c407214339f6
--- /dev/null
+++ b/drivers/net/atl1/atl1_param.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved.
+ * Copyright(c) 2006 Chris Snook <csnook@redhat.com>
+ * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * 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., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/moduleparam.h>
+#include "atl1.h"
+
+/*
+ * This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+#define ATL1_MAX_NIC 4
+
+#define OPTION_UNSET -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED 1
+
+#define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET }
+
+/*
+ * Interrupt Moderate Timer in units of 2 us
+ *
+ * Valid Range: 10-65535
+ *
+ * Default Value: 100 (200us)
+ */
+static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int num_int_mod_timer = 0;
+module_param_array_named(int_mod_timer, int_mod_timer, int, &num_int_mod_timer, 0);
+MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer");
+
+/*
+ * flash_vendor
+ *
+ * Valid Range: 0-2
+ *
+ * 0 - Atmel
+ * 1 - SST
+ * 2 - ST
+ *
+ * Default Value: 0
+ */
+static int __devinitdata flash_vendor[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int num_flash_vendor = 0;
+module_param_array_named(flash_vendor, flash_vendor, int, &num_flash_vendor, 0);
+MODULE_PARM_DESC(flash_vendor, "SPI flash vendor");
+
+#define DEFAULT_INT_MOD_CNT 100 /* 200us */
+#define MAX_INT_MOD_CNT 65000
+#define MIN_INT_MOD_CNT 50
+
+#define FLASH_VENDOR_DEFAULT 0
+#define FLASH_VENDOR_MIN 0
+#define FLASH_VENDOR_MAX 2
+
+struct atl1_option {
+ enum { enable_option, range_option, list_option } type;
+ char *name;
+ char *err;
+ int def;
+ union {
+ struct { /* range_option info */
+ int min;
+ int max;
+ } r;
+ struct { /* list_option info */
+ int nr;
+ struct atl1_opt_list {
+ int i;
+ char *str;
+ } *p;
+ } l;
+ } arg;
+};
+
+static int __devinit atl1_validate_option(int *value, struct atl1_option *opt)
+{
+ if (*value == OPTION_UNSET) {
+ *value = opt->def;
+ return 0;
+ }
+
+ switch (opt->type) {
+ case enable_option:
+ switch (*value) {
+ case OPTION_ENABLED:
+ printk(KERN_INFO "%s: %s Enabled\n", atl1_driver_name,
+ opt->name);
+ return 0;
+ case OPTION_DISABLED:
+ printk(KERN_INFO "%s: %s Disabled\n", atl1_driver_name,
+ opt->name);
+ return 0;
+ }
+ break;
+ case range_option:
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ printk(KERN_INFO "%s: %s set to %i\n",
+ atl1_driver_name, opt->name, *value);
+ return 0;
+ }
+ break;
+ case list_option:{
+ int i;
+ struct atl1_opt_list *ent;
+
+ for (i = 0; i < opt->arg.l.nr; i++) {
+ ent = &opt->arg.l.p[i];
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
+ printk(KERN_INFO "%s: %s\n",
+ atl1_driver_name, ent->str);
+ return 0;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ printk(KERN_INFO "%s: invalid %s specified (%i) %s\n",
+ atl1_driver_name, opt->name, *value, opt->err);
+ *value = opt->def;
+ return -1;
+}
+
+/*
+ * atl1_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input. If an invalid value is given, or if no user specified
+ * value exists, a default value is used. The final value is stored
+ * in a variable in the adapter structure.
+ */
+void __devinit atl1_check_options(struct atl1_adapter *adapter)
+{
+ int bd = adapter->bd_number;
+ if (bd >= ATL1_MAX_NIC) {
+ printk(KERN_NOTICE "%s: warning: no configuration for board #%i\n",
+ atl1_driver_name, bd);
+ printk(KERN_NOTICE "%s: using defaults for all values\n",
+ atl1_driver_name);
+ }
+ { /* Interrupt Moderate Timer */
+ struct atl1_option opt = {
+ .type = range_option,
+ .name = "Interrupt Moderator Timer",
+ .err = "using default of "
+ __MODULE_STRING(DEFAULT_INT_MOD_CNT),
+ .def = DEFAULT_INT_MOD_CNT,
+ .arg = {.r =
+ {.min = MIN_INT_MOD_CNT,.max = MAX_INT_MOD_CNT}}
+ };
+ int val;
+ if (num_int_mod_timer > bd) {
+ val = int_mod_timer[bd];
+ atl1_validate_option(&val, &opt);
+ adapter->imt = (u16) val;
+ } else
+ adapter->imt = (u16) (opt.def);
+ }
+
+ { /* Flash Vendor */
+ struct atl1_option opt = {
+ .type = range_option,
+ .name = "SPI Flash Vendor",
+ .err = "using default of "
+ __MODULE_STRING(FLASH_VENDOR_DEFAULT),
+ .def = DEFAULT_INT_MOD_CNT,
+ .arg = {.r =
+ {.min = FLASH_VENDOR_MIN,.max =
+ FLASH_VENDOR_MAX}}
+ };
+ int val;
+ if (num_flash_vendor > bd) {
+ val = flash_vendor[bd];
+ atl1_validate_option(&val, &opt);
+ adapter->hw.flash_vendor = (u8) val;
+ } else
+ adapter->hw.flash_vendor = (u8) (opt.def);
+ }
+}
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 32923162179e..217a2eedee0a 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -184,7 +184,7 @@ static int tlb_initialize(struct bonding *bond)
spin_lock_init(&(bond_info->tx_hashtbl_lock));
- new_hashtbl = kmalloc(size, GFP_KERNEL);
+ new_hashtbl = kzalloc(size, GFP_KERNEL);
if (!new_hashtbl) {
printk(KERN_ERR DRV_NAME
": %s: Error: Failed to allocate TLB hash table\n",
@@ -195,8 +195,6 @@ static int tlb_initialize(struct bonding *bond)
bond_info->tx_hashtbl = new_hashtbl;
- memset(bond_info->tx_hashtbl, 0, size);
-
for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index d3801a00d3d5..8ce8fec615ba 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1343,14 +1343,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
"inaccurate.\n", bond_dev->name, slave_dev->name);
}
- new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
+ new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
if (!new_slave) {
res = -ENOMEM;
goto err_undo_flags;
}
- memset(new_slave, 0, sizeof(struct slave));
-
/* save slave's original flags before calling
* netdev_set_master and dev_open
*/
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index dfa035a1ad45..c67f7d3c2f92 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -74,8 +74,6 @@ enum {
#define EEPROM_MAGIC 0x38E2F10C
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
-
#define CH_DEVICE(devid, ssid, idx) \
{ PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx }
@@ -434,11 +432,12 @@ static int setup_sge_qsets(struct adapter *adap)
return 0;
}
-static ssize_t attr_show(struct class_device *cd, char *buf,
+static ssize_t attr_show(struct device *d, struct device_attribute *attr,
+ char *buf,
ssize_t(*format) (struct adapter *, char *))
{
ssize_t len;
- struct adapter *adap = to_net_dev(cd)->priv;
+ struct adapter *adap = to_net_dev(d)->priv;
/* Synchronize with ioctls that may shut down the device */
rtnl_lock();
@@ -447,14 +446,15 @@ static ssize_t attr_show(struct class_device *cd, char *buf,
return len;
}
-static ssize_t attr_store(struct class_device *cd, const char *buf, size_t len,
+static ssize_t attr_store(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t len,
ssize_t(*set) (struct adapter *, unsigned int),
unsigned int min_val, unsigned int max_val)
{
char *endp;
ssize_t ret;
unsigned int val;
- struct adapter *adap = to_net_dev(cd)->priv;
+ struct adapter *adap = to_net_dev(d)->priv;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -476,9 +476,10 @@ static ssize_t format_##name(struct adapter *adap, char *buf) \
{ \
return sprintf(buf, "%u\n", val_expr); \
} \
-static ssize_t show_##name(struct class_device *cd, char *buf) \
+static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
+ char *buf) \
{ \
- return attr_show(cd, buf, format_##name); \
+ return attr_show(d, attr, buf, format_##name); \
}
static ssize_t set_nfilters(struct adapter *adap, unsigned int val)
@@ -493,10 +494,10 @@ static ssize_t set_nfilters(struct adapter *adap, unsigned int val)
return 0;
}
-static ssize_t store_nfilters(struct class_device *cd, const char *buf,
- size_t len)
+static ssize_t store_nfilters(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t len)
{
- return attr_store(cd, buf, len, set_nfilters, 0, ~0);
+ return attr_store(d, attr, buf, len, set_nfilters, 0, ~0);
}
static ssize_t set_nservers(struct adapter *adap, unsigned int val)
@@ -509,38 +510,39 @@ static ssize_t set_nservers(struct adapter *adap, unsigned int val)
return 0;
}
-static ssize_t store_nservers(struct class_device *cd, const char *buf,
- size_t len)
+static ssize_t store_nservers(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t len)
{
- return attr_store(cd, buf, len, set_nservers, 0, ~0);
+ return attr_store(d, attr, buf, len, set_nservers, 0, ~0);
}
#define CXGB3_ATTR_R(name, val_expr) \
CXGB3_SHOW(name, val_expr) \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
#define CXGB3_ATTR_RW(name, val_expr, store_method) \
CXGB3_SHOW(name, val_expr) \
-static CLASS_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_method)
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_method)
CXGB3_ATTR_R(cam_size, t3_mc5_size(&adap->mc5));
CXGB3_ATTR_RW(nfilters, adap->params.mc5.nfilters, store_nfilters);
CXGB3_ATTR_RW(nservers, adap->params.mc5.nservers, store_nservers);
static struct attribute *cxgb3_attrs[] = {
- &class_device_attr_cam_size.attr,
- &class_device_attr_nfilters.attr,
- &class_device_attr_nservers.attr,
+ &dev_attr_cam_size.attr,
+ &dev_attr_nfilters.attr,
+ &dev_attr_nservers.attr,
NULL
};
static struct attribute_group cxgb3_attr_group = {.attrs = cxgb3_attrs };
-static ssize_t tm_attr_show(struct class_device *cd, char *buf, int sched)
+static ssize_t tm_attr_show(struct device *d, struct device_attribute *attr,
+ char *buf, int sched)
{
ssize_t len;
unsigned int v, addr, bpt, cpt;
- struct adapter *adap = to_net_dev(cd)->priv;
+ struct adapter *adap = to_net_dev(d)->priv;
addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2;
rtnl_lock();
@@ -560,13 +562,13 @@ static ssize_t tm_attr_show(struct class_device *cd, char *buf, int sched)
return len;
}
-static ssize_t tm_attr_store(struct class_device *cd, const char *buf,
- size_t len, int sched)
+static ssize_t tm_attr_store(struct device *d, struct device_attribute *attr,
+ const char *buf, size_t len, int sched)
{
char *endp;
ssize_t ret;
unsigned int val;
- struct adapter *adap = to_net_dev(cd)->priv;
+ struct adapter *adap = to_net_dev(d)->priv;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -584,15 +586,17 @@ static ssize_t tm_attr_store(struct class_device *cd, const char *buf,
}
#define TM_ATTR(name, sched) \
-static ssize_t show_##name(struct class_device *cd, char *buf) \
+static ssize_t show_##name(struct device *d, struct device_attribute *attr, \
+ char *buf) \
{ \
- return tm_attr_show(cd, buf, sched); \
+ return tm_attr_show(d, attr, buf, sched); \
} \
-static ssize_t store_##name(struct class_device *cd, const char *buf, size_t len) \
+static ssize_t store_##name(struct device *d, struct device_attribute *attr, \
+ const char *buf, size_t len) \
{ \
- return tm_attr_store(cd, buf, len, sched); \
+ return tm_attr_store(d, attr, buf, len, sched); \
} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
TM_ATTR(sched0, 0);
TM_ATTR(sched1, 1);
@@ -604,14 +608,14 @@ TM_ATTR(sched6, 6);
TM_ATTR(sched7, 7);
static struct attribute *offload_attrs[] = {
- &class_device_attr_sched0.attr,
- &class_device_attr_sched1.attr,
- &class_device_attr_sched2.attr,
- &class_device_attr_sched3.attr,
- &class_device_attr_sched4.attr,
- &class_device_attr_sched5.attr,
- &class_device_attr_sched6.attr,
- &class_device_attr_sched7.attr,
+ &dev_attr_sched0.attr,
+ &dev_attr_sched1.attr,
+ &dev_attr_sched2.attr,
+ &dev_attr_sched3.attr,
+ &dev_attr_sched4.attr,
+ &dev_attr_sched5.attr,
+ &dev_attr_sched6.attr,
+ &dev_attr_sched7.attr,
NULL
};
@@ -836,7 +840,7 @@ static int offload_open(struct net_device *dev)
init_smt(adapter);
/* Never mind if the next step fails */
- sysfs_create_group(&tdev->lldev->class_dev.kobj, &offload_attr_group);
+ sysfs_create_group(&tdev->lldev->dev.kobj, &offload_attr_group);
/* Call back all registered clients */
cxgb3_add_clients(tdev);
@@ -861,7 +865,7 @@ static int offload_close(struct t3cdev *tdev)
/* Call back all registered clients */
cxgb3_remove_clients(tdev);
- sysfs_remove_group(&tdev->lldev->class_dev.kobj, &offload_attr_group);
+ sysfs_remove_group(&tdev->lldev->dev.kobj, &offload_attr_group);
tdev->lldev = NULL;
cxgb3_set_dummy_ops(tdev);
@@ -2420,7 +2424,7 @@ static int __devinit init_one(struct pci_dev *pdev,
else if (msi > 0 && pci_enable_msi(pdev) == 0)
adapter->flags |= USING_MSI;
- err = sysfs_create_group(&adapter->port[0]->class_dev.kobj,
+ err = sysfs_create_group(&adapter->port[0]->dev.kobj,
&cxgb3_attr_group);
print_port_info(adapter, ai);
@@ -2452,7 +2456,7 @@ static void __devexit remove_one(struct pci_dev *pdev)
struct adapter *adapter = dev->priv;
t3_sge_stop(adapter);
- sysfs_remove_group(&adapter->port[0]->class_dev.kobj,
+ sysfs_remove_group(&adapter->port[0]->dev.kobj,
&cxgb3_attr_group);
for_each_port(adapter, i)
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index c3a02d613382..c6b726643185 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -396,7 +396,7 @@ static int rx_offload_blackhole(struct t3cdev *dev, struct sk_buff **skbs,
int n)
{
CH_ERR(tdev2adap(dev), "%d unexpected offload packets, first data %u\n",
- n, ntohl(*(u32 *)skbs[0]->data));
+ n, ntohl(*(__be32 *)skbs[0]->data));
while (n--)
dev_kfree_skb_any(skbs[n]);
return 0;
@@ -755,7 +755,7 @@ static int do_trace(struct t3cdev *dev, struct sk_buff *skb)
{
struct cpl_trace_pkt *p = cplhdr(skb);
- skb->protocol = 0xffff;
+ skb->protocol = htons(0xffff);
skb->dev = dev->lldev;
skb_pull(skb, sizeof(*p));
skb->mac.raw = skb->data;
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index c62d9c6363c6..b2b0a96218ca 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -355,8 +355,7 @@ e21_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring
mem_on(ioaddr, shared_mem, (ring_offset>>8));
- /* Packet is always in one chunk -- we can copy + cksum. */
- eth_io_copy_and_sum(skb, ei_status.mem + (ring_offset & 0xff), count, 0);
+ memcpy_fromio(skb->data, ei_status.mem + (ring_offset & 0xff), count);
mem_off(ioaddr);
}
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 2d2ea94a00bb..822e5bfd1a71 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -375,7 +375,7 @@ static void es_block_input(struct net_device *dev, int count, struct sk_buff *sk
memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
} else {
/* Packet is in one chunk. */
- eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ memcpy_fromio(skb->data, xfer_start, count);
}
}
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index 24f6050fbf33..8ca57a0a4c11 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -49,6 +49,7 @@
#include <linux/skbuff.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/bitrev.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index b3bf86422734..d98e53efa2ef 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2780,7 +2780,6 @@ static const struct ethtool_ops mv643xx_ethtool_ops = {
.get_link = mv643xx_eth_get_link,
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
- .get_strings = mv643xx_get_strings,
.get_stats_count = mv643xx_get_stats_count,
.get_ethtool_stats = mv643xx_get_ethtool_stats,
.get_strings = mv643xx_get_strings,
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 577babd4c938..5598d86380b4 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -2016,7 +2016,7 @@ static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
if (!skb)
goto err_out;
- skb_reserve(skb, (align - 1) & (u32)skb->data);
+ skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
*sk_buff = skb;
mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
@@ -2487,7 +2487,7 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
skb = dev_alloc_skb(pkt_size + align);
if (skb) {
- skb_reserve(skb, (align - 1) & (u32)skb->data);
+ skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
*sk_buff = skb;
rtl8169_mark_to_asic(desc, rx_buf_sz);
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 639fbc0f16f3..8646b64994ab 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -7298,7 +7298,7 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro)
{
struct iphdr *ip = lro->iph;
struct tcphdr *tcp = lro->tcph;
- u16 nchk;
+ __sum16 nchk;
struct stat_block *statinfo = sp->mac_control.stats_info;
DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index a5e1a513deb5..0de0c65f945a 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -727,12 +727,12 @@ struct lro {
struct iphdr *iph;
struct tcphdr *tcph;
u32 tcp_next_seq;
- u32 tcp_ack;
+ __be32 tcp_ack;
int total_len;
int frags_len;
int sg_num;
int in_use;
- u16 window;
+ __be16 window;
u32 cur_tsval;
u32 cur_tsecr;
u8 saw_ts;
@@ -1005,7 +1005,7 @@ static int s2io_set_swapper(struct s2io_nic * sp);
static void s2io_card_down(struct s2io_nic *nic);
static int s2io_card_up(struct s2io_nic *nic);
static int get_xena_rev_id(struct pci_dev *pdev);
-static int wait_for_cmd_complete(void *addr, u64 busy_bit);
+static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit);
static int s2io_add_isr(struct s2io_nic * sp);
static void s2io_rem_isr(struct s2io_nic * sp);
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index a0806d262fc6..2f4b1de7a2b4 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -1343,15 +1343,12 @@ static int __init slip_init(void)
printk(KERN_INFO "SLIP linefill/keepalive option.\n");
#endif
- slip_devs = kmalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
+ slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
if (!slip_devs) {
printk(KERN_ERR "SLIP: Can't allocate slip devices array! Uaargh! (-> No SLIP available)\n");
return -ENOMEM;
}
- /* Clear the pointer array, we allocate devices when we need them */
- memset(slip_devs, 0, sizeof(struct net_device *)*slip_maxdev);
-
/* Fill in our line protocol discipline, and register it */
if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) {
printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index 7122932eac90..ae1ae343beed 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -482,8 +482,7 @@ static void ultramca_block_input(struct net_device *dev, int count, struct sk_bu
count -= semi_count;
memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
} else {
- /* Packet is in one chunk -- we can copy + cksum. */
- eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ memcpy_fromio(skb->data, xfer_start, count);
}
}
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index d70bc9795346..a52b22d7db65 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -454,8 +454,7 @@ ultra_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ri
count -= semi_count;
memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
} else {
- /* Packet is in one chunk -- we can copy + cksum. */
- eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ memcpy_fromio(skb->data, xfer_start, count);
}
outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index 2c5319c62fa5..88a30e56c64c 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -395,8 +395,7 @@ static void ultra32_block_input(struct net_device *dev,
memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
}
} else {
- /* Packet is in one chunk -- we can copy + cksum. */
- eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ memcpy_fromio(skb->data, xfer_start, count);
}
}
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index bf6ff39e02bb..64ed8ff5b03a 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1907,7 +1907,7 @@ spider_net_stop(struct net_device *netdev)
spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
/* free_irq(netdev->irq, netdev);*/
- free_irq(to_pci_dev(netdev->class_dev.dev)->irq, netdev);
+ free_irq(to_pci_dev(netdev->dev.parent)->irq, netdev);
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
SPIDER_NET_DMA_TX_FEND_VALUE);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 135c0987deae..e136bae61970 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3380,7 +3380,7 @@ next_pkt:
}
next_pkt_nopost:
sw_idx++;
- sw_idx %= TG3_RX_RCB_RING_SIZE(tp);
+ sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1);
/* Refresh hw_idx to see if there is new work */
if (sw_idx == hw_idx) {
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index abb8611c5a91..31c97a6591a4 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1709,75 +1709,13 @@ static void adjust_link(struct net_device *dev)
if (mii_info->speed != ugeth->oldspeed) {
switch (mii_info->speed) {
case 1000:
-#ifdef CONFIG_PPC_MPC836x
-/* FIXME: This code is for 100Mbs BUG fixing,
-remove this when it is fixed!!! */
- if (ugeth->ug_info->enet_interface ==
- ENET_1000_GMII)
- /* Run the commands which initialize the PHY */
- {
- tempval =
- (u32) mii_info->mdio_read(ugeth->
- dev, mii_info->mii_id, 0x1b);
- tempval |= 0x000f;
- mii_info->mdio_write(ugeth->dev,
- mii_info->mii_id, 0x1b,
- (u16) tempval);
- tempval =
- (u32) mii_info->mdio_read(ugeth->
- dev, mii_info->mii_id,
- MII_BMCR);
- mii_info->mdio_write(ugeth->dev,
- mii_info->mii_id, MII_BMCR,
- (u16) (tempval | BMCR_RESET));
- } else if (ugeth->ug_info->enet_interface ==
- ENET_1000_RGMII)
- /* Run the commands which initialize the PHY */
- {
- tempval =
- (u32) mii_info->mdio_read(ugeth->
- dev, mii_info->mii_id, 0x1b);
- tempval = (tempval & ~0x000f) | 0x000b;
- mii_info->mdio_write(ugeth->dev,
- mii_info->mii_id, 0x1b,
- (u16) tempval);
- tempval =
- (u32) mii_info->mdio_read(ugeth->
- dev, mii_info->mii_id,
- MII_BMCR);
- mii_info->mdio_write(ugeth->dev,
- mii_info->mii_id, MII_BMCR,
- (u16) (tempval | BMCR_RESET));
- }
- msleep(4000);
-#endif /* CONFIG_MPC8360 */
- adjust_enet_interface(ugeth);
+ ugeth->ug_info->enet_interface = ENET_1000_RGMII;
break;
case 100:
- case 10:
-#ifdef CONFIG_PPC_MPC836x
-/* FIXME: This code is for 100Mbs BUG fixing,
-remove this lines when it will be fixed!!! */
ugeth->ug_info->enet_interface = ENET_100_RGMII;
- tempval =
- (u32) mii_info->mdio_read(ugeth->dev,
- mii_info->mii_id,
- 0x1b);
- tempval = (tempval & ~0x000f) | 0x000b;
- mii_info->mdio_write(ugeth->dev,
- mii_info->mii_id, 0x1b,
- (u16) tempval);
- tempval =
- (u32) mii_info->mdio_read(ugeth->dev,
- mii_info->mii_id,
- MII_BMCR);
- mii_info->mdio_write(ugeth->dev,
- mii_info->mii_id, MII_BMCR,
- (u16) (tempval |
- BMCR_RESET));
- msleep(4000);
-#endif /* CONFIG_MPC8360 */
- adjust_enet_interface(ugeth);
+ break;
+ case 10:
+ ugeth->ug_info->enet_interface = ENET_10_RGMII;
break;
default:
ugeth_warn
@@ -1785,6 +1723,7 @@ remove this lines when it will be fixed!!! */
dev->name, mii_info->speed);
break;
}
+ adjust_enet_interface(ugeth);
ugeth_info("%s: Speed %dBT", dev->name,
mii_info->speed);
@@ -4133,6 +4072,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
static int mii_mng_configured = 0;
const phandle *ph;
const unsigned int *prop;
+ const void *mac_addr;
ugeth_vdbg("%s: IN", __FUNCTION__);
@@ -4258,7 +4198,12 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
ugeth->ug_info = ug_info;
ugeth->dev = dev;
- memcpy(dev->dev_addr, get_property(np, "mac-address", NULL), 6);
+
+ mac_addr = get_property(np, "mac-address", NULL);
+ if (mac_addr == NULL)
+ mac_addr = get_property(np, "local-mac-address", NULL);
+ if (mac_addr)
+ memcpy(dev->dev_addr, mac_addr, 6);
return 0;
}
diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c
index 3c86592ce03c..6fda6d88be49 100644
--- a/drivers/net/ucc_geth_phy.c
+++ b/drivers/net/ucc_geth_phy.c
@@ -376,6 +376,8 @@ static int marvell_init(struct ugeth_mii_info *mii_info)
ugphy_vdbg("%s: IN", __FUNCTION__);
ucc_geth_phy_write(mii_info, 0x14, 0x0cd2);
+ ucc_geth_phy_write(mii_info, 0x1b,
+ (ucc_geth_phy_read(mii_info, 0x1b) & ~0x000f) | 0x000b);
ucc_geth_phy_write(mii_info, MII_BMCR,
ucc_geth_phy_read(mii_info, MII_BMCR) | BMCR_RESET);
msleep(4000);
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index 79b2d5454d6b..bc156b51678a 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -101,8 +101,8 @@ typedef struct port_s {
typedef struct card_s {
int type; /* RSV, X21, etc. */
int n_ports; /* 1 or 2 ports */
- u8* __iomem rambase; /* buffer memory base (virtual) */
- u8* __iomem scabase; /* SCA memory base (virtual) */
+ u8 __iomem *rambase; /* buffer memory base (virtual) */
+ u8 __iomem *scabase; /* SCA memory base (virtual) */
plx9050 __iomem *plxbase; /* PLX registers memory base (virtual) */
u32 init_ctrl_value; /* Saved value - 9050 bug workaround */
u16 rx_ring_buffers; /* number of buffers in a ring */
@@ -134,7 +134,7 @@ typedef struct card_s {
static void pc300_set_iface(port_t *port)
{
card_t *card = port->card;
- u32* init_ctrl = &card->plxbase->init_ctrl;
+ u32 __iomem * init_ctrl = &card->plxbase->init_ctrl;
u16 msci = get_msci(port);
u8 rxs = port->rxs & CLK_BRG_MASK;
u8 txs = port->txs & CLK_BRG_MASK;
@@ -393,7 +393,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
/* PLX PCI 9050 workaround for local configuration register read bug */
pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, scaphys);
- card->init_ctrl_value = readl(&((plx9050*)card->scabase)->init_ctrl);
+ card->init_ctrl_value = readl(&((plx9050 __iomem *)card->scabase)->init_ctrl);
pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, plxphys);
/* Reset PLX */
@@ -519,10 +519,10 @@ static struct pci_device_id pc300_pci_tbl[] __devinitdata = {
static struct pci_driver pc300_pci_driver = {
- name: "PC300",
- id_table: pc300_pci_tbl,
- probe: pc300_pci_init_one,
- remove: pc300_pci_remove_one,
+ .name = "PC300",
+ .id_table = pc300_pci_tbl,
+ .probe = pc300_pci_init_one,
+ .remove = pc300_pci_remove_one,
};
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index 7f38012b9c92..a0326818ff2f 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -433,7 +433,7 @@ wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_
memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
} else {
/* Packet is in one chunk -- we can copy + cksum. */
- eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ memcpy_fromio(skb->data, xfer_start, count);
}
/* Turn off 16 bit access so that reboot works. ISA brain-damage */
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index bbf025874d0c..4dbef0762376 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -722,7 +722,7 @@ static int __init init_m32r_pcc(void)
/* Set up interrupt handler(s) */
for (i = 0 ; i < pcc_sockets ; i++) {
- socket[i].socket.dev.dev = &pcc_device.dev;
+ socket[i].socket.dev.parent = &pcc_device.dev;
socket[i].socket.ops = &pcc_operations;
socket[i].socket.resource_ops = &pccard_static_ops;
socket[i].socket.owner = THIS_MODULE;
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 94d3df62a5fa..82f2ac87ccd4 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -305,7 +305,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
case RTC_IRQP_READ:
if (ops->irq_set_freq)
- err = put_user(rtc->irq_freq, (unsigned long *) arg);
+ err = put_user(rtc->irq_freq, (unsigned long __user *)uarg);
break;
case RTC_IRQP_SET:
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index a138b1510093..3a1a958fb5f2 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -3,7 +3,7 @@
*
* Character device driver for reading z/VM *MONITOR service records.
*
- * Copyright (C) 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
*
* Author: Gerald Schaefer <geraldsc@de.ibm.com>
*/
@@ -22,7 +22,7 @@
#include <asm/ebcdic.h>
#include <asm/extmem.h>
#include <linux/poll.h>
-#include "../net/iucv.h"
+#include <net/iucv/iucv.h>
//#define MON_DEBUG /* Debug messages on/off */
@@ -50,14 +50,13 @@ static char mon_dcss_name[9] = "MONDCSS\0";
struct mon_msg {
u32 pos;
u32 mca_offset;
- iucv_MessagePending local_eib;
+ struct iucv_message msg;
char msglim_reached;
char replied_msglim;
};
struct mon_private {
- u16 pathid;
- iucv_handle_t iucv_handle;
+ struct iucv_path *path;
struct mon_msg *msg_array[MON_MSGLIM];
unsigned int write_index;
unsigned int read_index;
@@ -75,8 +74,6 @@ static unsigned long mon_dcss_end;
static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue);
static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue);
-static u8 iucv_host[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
static u8 user_data_connect[16] = {
/* Version code, must be 0x01 for shared mode */
0x01,
@@ -100,8 +97,7 @@ static u8 user_data_sever[16] = {
* Create the 8 bytes EBCDIC DCSS segment name from
* an ASCII name, incl. padding
*/
-static inline void
-dcss_mkname(char *ascii_name, char *ebcdic_name)
+static inline void dcss_mkname(char *ascii_name, char *ebcdic_name)
{
int i;
@@ -119,8 +115,7 @@ dcss_mkname(char *ascii_name, char *ebcdic_name)
* print appropriate error message for segment_load()/segment_type()
* return code
*/
-static void
-mon_segment_warn(int rc, char* seg_name)
+static void mon_segment_warn(int rc, char* seg_name)
{
switch (rc) {
case -ENOENT:
@@ -166,44 +161,37 @@ mon_segment_warn(int rc, char* seg_name)
}
}
-static inline unsigned long
-mon_mca_start(struct mon_msg *monmsg)
+static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
{
- return monmsg->local_eib.ln1msg1.iprmmsg1_u32;
+ return *(u32 *) &monmsg->msg.rmmsg;
}
-static inline unsigned long
-mon_mca_end(struct mon_msg *monmsg)
+static inline unsigned long mon_mca_end(struct mon_msg *monmsg)
{
- return monmsg->local_eib.ln1msg2.ipbfln1f;
+ return *(u32 *) &monmsg->msg.rmmsg[4];
}
-static inline u8
-mon_mca_type(struct mon_msg *monmsg, u8 index)
+static inline u8 mon_mca_type(struct mon_msg *monmsg, u8 index)
{
return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index);
}
-static inline u32
-mon_mca_size(struct mon_msg *monmsg)
+static inline u32 mon_mca_size(struct mon_msg *monmsg)
{
return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1;
}
-static inline u32
-mon_rec_start(struct mon_msg *monmsg)
+static inline u32 mon_rec_start(struct mon_msg *monmsg)
{
return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4));
}
-static inline u32
-mon_rec_end(struct mon_msg *monmsg)
+static inline u32 mon_rec_end(struct mon_msg *monmsg)
{
return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));
}
-static inline int
-mon_check_mca(struct mon_msg *monmsg)
+static inline int mon_check_mca(struct mon_msg *monmsg)
{
if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
(mon_rec_start(monmsg) < mon_dcss_start) ||
@@ -221,20 +209,17 @@ mon_check_mca(struct mon_msg *monmsg)
return 0;
}
-static inline int
-mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
+static inline int mon_send_reply(struct mon_msg *monmsg,
+ struct mon_private *monpriv)
{
- u8 prmmsg[8];
int rc;
P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
"0x%08X\n\n",
- monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,
- monmsg->local_eib.iptrgcls);
- rc = iucv_reply_prmmsg(monmsg->local_eib.ippathid,
- monmsg->local_eib.ipmsgid,
- monmsg->local_eib.iptrgcls,
- 0, prmmsg);
+ monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
+
+ rc = iucv_message_reply(monpriv->path, &monmsg->msg,
+ IUCV_IPRMDATA, NULL, 0);
atomic_dec(&monpriv->msglim_count);
if (likely(!monmsg->msglim_reached)) {
monmsg->pos = 0;
@@ -251,10 +236,19 @@ mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
return 0;
}
-static inline struct mon_private *
-mon_alloc_mem(void)
+static inline void mon_free_mem(struct mon_private *monpriv)
+{
+ int i;
+
+ for (i = 0; i < MON_MSGLIM; i++)
+ if (monpriv->msg_array[i])
+ kfree(monpriv->msg_array[i]);
+ kfree(monpriv);
+}
+
+static inline struct mon_private *mon_alloc_mem(void)
{
- int i,j;
+ int i;
struct mon_private *monpriv;
monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
@@ -267,16 +261,15 @@ mon_alloc_mem(void)
GFP_KERNEL);
if (!monpriv->msg_array[i]) {
P_ERROR("open, no memory for msg_array\n");
- for (j = 0; j < i; j++)
- kfree(monpriv->msg_array[j]);
+ mon_free_mem(monpriv);
return NULL;
}
}
return monpriv;
}
-static inline void
-mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
+static inline void mon_read_debug(struct mon_msg *monmsg,
+ struct mon_private *monpriv)
{
#ifdef MON_DEBUG
u8 msg_type[2], mca_type;
@@ -284,7 +277,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;
- memcpy(msg_type, &monmsg->local_eib.iptrgcls, 2);
+ memcpy(msg_type, &monmsg->msg.class, 2);
EBCASC(msg_type, 2);
mca_type = mon_mca_type(monmsg, 0);
EBCASC(&mca_type, 1);
@@ -292,8 +285,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
monpriv->read_index, monpriv->write_index);
P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
- monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,
- monmsg->local_eib.iptrgcls);
+ monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
@@ -306,8 +298,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
#endif
}
-static inline void
-mon_next_mca(struct mon_msg *monmsg)
+static inline void mon_next_mca(struct mon_msg *monmsg)
{
if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
return;
@@ -316,8 +307,7 @@ mon_next_mca(struct mon_msg *monmsg)
monmsg->pos = 0;
}
-static inline struct mon_msg *
-mon_next_message(struct mon_private *monpriv)
+static inline struct mon_msg *mon_next_message(struct mon_private *monpriv)
{
struct mon_msg *monmsg;
@@ -342,39 +332,37 @@ mon_next_message(struct mon_private *monpriv)
/******************************************************************************
* IUCV handler *
*****************************************************************************/
-static void
-mon_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data)
+static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
{
- struct mon_private *monpriv = (struct mon_private *) pgm_data;
+ struct mon_private *monpriv = path->private;
P_DEBUG("IUCV connection completed\n");
P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
"0x%02X, Sample = 0x%02X\n",
- eib->ipuser[0], eib->ipuser[1], eib->ipuser[2]);
+ ipuser[0], ipuser[1], ipuser[2]);
atomic_set(&monpriv->iucv_connected, 1);
wake_up(&mon_conn_wait_queue);
}
-static void
-mon_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data)
+static void mon_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
{
- struct mon_private *monpriv = (struct mon_private *) pgm_data;
+ struct mon_private *monpriv = path->private;
- P_ERROR("IUCV connection severed with rc = 0x%X\n",
- (u8) eib->ipuser[0]);
+ P_ERROR("IUCV connection severed with rc = 0x%X\n", ipuser[0]);
+ iucv_path_sever(path, NULL);
atomic_set(&monpriv->iucv_severed, 1);
wake_up(&mon_conn_wait_queue);
wake_up_interruptible(&mon_read_wait_queue);
}
-static void
-mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
+static void mon_iucv_message_pending(struct iucv_path *path,
+ struct iucv_message *msg)
{
- struct mon_private *monpriv = (struct mon_private *) pgm_data;
+ struct mon_private *monpriv = path->private;
P_DEBUG("IUCV message pending\n");
- memcpy(&monpriv->msg_array[monpriv->write_index]->local_eib, eib,
- sizeof(iucv_MessagePending));
+ memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
+ msg, sizeof(*msg));
if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
P_WARNING("IUCV message pending, message limit (%i) reached\n",
MON_MSGLIM);
@@ -385,54 +373,45 @@ mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
wake_up_interruptible(&mon_read_wait_queue);
}
-static iucv_interrupt_ops_t mon_iucvops = {
- .ConnectionComplete = mon_iucv_ConnectionComplete,
- .ConnectionSevered = mon_iucv_ConnectionSevered,
- .MessagePending = mon_iucv_MessagePending,
+static struct iucv_handler monreader_iucv_handler = {
+ .path_complete = mon_iucv_path_complete,
+ .path_severed = mon_iucv_path_severed,
+ .message_pending = mon_iucv_message_pending,
};
/******************************************************************************
* file operations *
*****************************************************************************/
-static int
-mon_open(struct inode *inode, struct file *filp)
+static int mon_open(struct inode *inode, struct file *filp)
{
- int rc, i;
struct mon_private *monpriv;
+ int rc;
/*
* only one user allowed
*/
+ rc = -EBUSY;
if (test_and_set_bit(MON_IN_USE, &mon_in_use))
- return -EBUSY;
+ goto out;
+ rc = -ENOMEM;
monpriv = mon_alloc_mem();
if (!monpriv)
- return -ENOMEM;
+ goto out_use;
/*
- * Register with IUCV and connect to *MONITOR service
+ * Connect to *MONITOR service
*/
- monpriv->iucv_handle = iucv_register_program("my_monreader ",
- MON_SERVICE,
- NULL,
- &mon_iucvops,
- monpriv);
- if (!monpriv->iucv_handle) {
- P_ERROR("failed to register with iucv driver\n");
- rc = -EIO;
- goto out_error;
- }
- P_INFO("open, registered with IUCV\n");
-
- rc = iucv_connect(&monpriv->pathid, MON_MSGLIM, user_data_connect,
- MON_SERVICE, iucv_host, IPRMDATA, NULL, NULL,
- monpriv->iucv_handle, NULL);
+ monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL);
+ if (!monpriv->path)
+ goto out_priv;
+ rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler,
+ MON_SERVICE, NULL, user_data_connect, monpriv);
if (rc) {
P_ERROR("iucv connection to *MONITOR failed with "
"IPUSER SEVER code = %i\n", rc);
rc = -EIO;
- goto out_unregister;
+ goto out_path;
}
/*
* Wait for connection confirmation
@@ -444,24 +423,23 @@ mon_open(struct inode *inode, struct file *filp)
atomic_set(&monpriv->iucv_severed, 0);
atomic_set(&monpriv->iucv_connected, 0);
rc = -EIO;
- goto out_unregister;
+ goto out_path;
}
P_INFO("open, established connection to *MONITOR service\n\n");
filp->private_data = monpriv;
return nonseekable_open(inode, filp);
-out_unregister:
- iucv_unregister_program(monpriv->iucv_handle);
-out_error:
- for (i = 0; i < MON_MSGLIM; i++)
- kfree(monpriv->msg_array[i]);
- kfree(monpriv);
+out_path:
+ kfree(monpriv->path);
+out_priv:
+ mon_free_mem(monpriv);
+out_use:
clear_bit(MON_IN_USE, &mon_in_use);
+out:
return rc;
}
-static int
-mon_close(struct inode *inode, struct file *filp)
+static int mon_close(struct inode *inode, struct file *filp)
{
int rc, i;
struct mon_private *monpriv = filp->private_data;
@@ -469,18 +447,12 @@ mon_close(struct inode *inode, struct file *filp)
/*
* Close IUCV connection and unregister
*/
- rc = iucv_sever(monpriv->pathid, user_data_sever);
+ rc = iucv_path_sever(monpriv->path, user_data_sever);
if (rc)
P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
else
P_INFO("close, terminated connection to *MONITOR service\n");
- rc = iucv_unregister_program(monpriv->iucv_handle);
- if (rc)
- P_ERROR("close, iucv_unregister failed with rc = %i\n", rc);
- else
- P_INFO("close, unregistered with IUCV\n");
-
atomic_set(&monpriv->iucv_severed, 0);
atomic_set(&monpriv->iucv_connected, 0);
atomic_set(&monpriv->read_ready, 0);
@@ -495,8 +467,8 @@ mon_close(struct inode *inode, struct file *filp)
return 0;
}
-static ssize_t
-mon_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
+static ssize_t mon_read(struct file *filp, char __user *data,
+ size_t count, loff_t *ppos)
{
struct mon_private *monpriv = filp->private_data;
struct mon_msg *monmsg;
@@ -563,8 +535,7 @@ out_copy:
return count;
}
-static unsigned int
-mon_poll(struct file *filp, struct poll_table_struct *p)
+static unsigned int mon_poll(struct file *filp, struct poll_table_struct *p)
{
struct mon_private *monpriv = filp->private_data;
@@ -593,8 +564,7 @@ static struct miscdevice mon_dev = {
/******************************************************************************
* module init/exit *
*****************************************************************************/
-static int __init
-mon_init(void)
+static int __init mon_init(void)
{
int rc;
@@ -603,22 +573,34 @@ mon_init(void)
return -ENODEV;
}
+ /*
+ * Register with IUCV and connect to *MONITOR service
+ */
+ rc = iucv_register(&monreader_iucv_handler, 1);
+ if (rc) {
+ P_ERROR("failed to register with iucv driver\n");
+ return rc;
+ }
+ P_INFO("open, registered with IUCV\n");
+
rc = segment_type(mon_dcss_name);
if (rc < 0) {
mon_segment_warn(rc, mon_dcss_name);
- return rc;
+ goto out_iucv;
}
if (rc != SEG_TYPE_SC) {
P_ERROR("segment %s has unsupported type, should be SC\n",
mon_dcss_name);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out_iucv;
}
rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
&mon_dcss_start, &mon_dcss_end);
if (rc < 0) {
mon_segment_warn(rc, mon_dcss_name);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out_iucv;
}
dcss_mkname(mon_dcss_name, &user_data_connect[8]);
@@ -634,14 +616,16 @@ mon_init(void)
out:
segment_unload(mon_dcss_name);
+out_iucv:
+ iucv_unregister(&monreader_iucv_handler, 1);
return rc;
}
-static void __exit
-mon_exit(void)
+static void __exit mon_exit(void)
{
segment_unload(mon_dcss_name);
WARN_ON(misc_deregister(&mon_dev) != 0);
+ iucv_unregister(&monreader_iucv_handler, 1);
return;
}
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 4f894dc2373b..8432a76b961e 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -3,7 +3,7 @@
* character device driver for reading z/VM system service records
*
*
- * Copyright (C) 2004 IBM Corporation
+ * Copyright 2004 IBM Corporation
* character device driver for reading z/VM system service records,
* Version 1.0
* Author(s): Xenia Tkatschow <xenia@us.ibm.com>
@@ -21,7 +21,7 @@
#include <asm/cpcmd.h>
#include <asm/debug.h>
#include <asm/ebcdic.h>
-#include "../net/iucv.h"
+#include <net/iucv/iucv.h>
#include <linux/kmod.h>
#include <linux/cdev.h>
#include <linux/device.h>
@@ -60,12 +60,11 @@ struct vmlogrdr_priv_t {
char system_service[8];
char internal_name[8];
char recording_name[8];
- u16 pathid;
+ struct iucv_path *path;
int connection_established;
int iucv_path_severed;
- iucv_MessagePending local_interrupt_buffer;
+ struct iucv_message local_interrupt_buffer;
atomic_t receive_ready;
- iucv_handle_t iucv_handle;
int minor_num;
char * buffer;
char * current_position;
@@ -97,37 +96,19 @@ static struct file_operations vmlogrdr_fops = {
};
-static u8 iucvMagic[16] = {
- 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
- 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
-};
+static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 ipuser[16]);
+static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 ipuser[16]);
+static void vmlogrdr_iucv_message_pending(struct iucv_path *,
+ struct iucv_message *);
-static u8 mask[] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+static struct iucv_handler vmlogrdr_iucv_handler = {
+ .path_complete = vmlogrdr_iucv_path_complete,
+ .path_severed = vmlogrdr_iucv_path_severed,
+ .message_pending = vmlogrdr_iucv_message_pending,
};
-static u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-
-static void
-vmlogrdr_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data);
-static void
-vmlogrdr_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data);
-static void
-vmlogrdr_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data);
-
-
-static iucv_interrupt_ops_t vmlogrdr_iucvops = {
- .ConnectionComplete = vmlogrdr_iucv_ConnectionComplete,
- .ConnectionSevered = vmlogrdr_iucv_ConnectionSevered,
- .MessagePending = vmlogrdr_iucv_MessagePending,
-};
-
static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
@@ -176,28 +157,29 @@ static struct cdev *vmlogrdr_cdev = NULL;
static int recording_class_AB;
-static void
-vmlogrdr_iucv_ConnectionComplete (iucv_ConnectionComplete * eib,
- void * pgm_data)
+static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
{
- struct vmlogrdr_priv_t * logptr = pgm_data;
+ struct vmlogrdr_priv_t * logptr = path->private;
+
spin_lock(&logptr->priv_lock);
logptr->connection_established = 1;
spin_unlock(&logptr->priv_lock);
wake_up(&conn_wait_queue);
- return;
}
-static void
-vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
+static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
{
- u8 reason = (u8) eib->ipuser[8];
- struct vmlogrdr_priv_t * logptr = pgm_data;
+ struct vmlogrdr_priv_t * logptr = path->private;
+ u8 reason = (u8) ipuser[8];
printk (KERN_ERR "vmlogrdr: connection severed with"
" reason %i\n", reason);
+ iucv_path_sever(path, NULL);
+ kfree(path);
+ logptr->path = NULL;
+
spin_lock(&logptr->priv_lock);
logptr->connection_established = 0;
logptr->iucv_path_severed = 1;
@@ -209,10 +191,10 @@ vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
}
-static void
-vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data)
+static void vmlogrdr_iucv_message_pending(struct iucv_path *path,
+ struct iucv_message *msg)
{
- struct vmlogrdr_priv_t * logptr = pgm_data;
+ struct vmlogrdr_priv_t * logptr = path->private;
/*
* This function is the bottom half so it should be quick.
@@ -220,15 +202,15 @@ vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data)
* the usage count
*/
spin_lock(&logptr->priv_lock);
- memcpy(&(logptr->local_interrupt_buffer), eib, sizeof(*eib));
+ memcpy(&logptr->local_interrupt_buffer, msg, sizeof(*msg));
atomic_inc(&logptr->receive_ready);
spin_unlock(&logptr->priv_lock);
wake_up_interruptible(&read_wait_queue);
}
-static int
-vmlogrdr_get_recording_class_AB(void) {
+static int vmlogrdr_get_recording_class_AB(void)
+{
char cp_command[]="QUERY COMMAND RECORDING ";
char cp_response[80];
char *tail;
@@ -258,8 +240,9 @@ vmlogrdr_get_recording_class_AB(void) {
}
-static int
-vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
+static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
+ int action, int purge)
+{
char cp_command[80];
char cp_response[160];
@@ -317,8 +300,7 @@ vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
}
-static int
-vmlogrdr_open (struct inode *inode, struct file *filp)
+static int vmlogrdr_open (struct inode *inode, struct file *filp)
{
int dev_num = 0;
struct vmlogrdr_priv_t * logptr = NULL;
@@ -328,10 +310,7 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
dev_num = iminor(inode);
if (dev_num > MAXMINOR)
return -ENODEV;
-
logptr = &sys_ser[dev_num];
- if (logptr == NULL)
- return -ENODEV;
/*
* only allow for blocking reads to be open
@@ -344,52 +323,38 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
if (logptr->dev_in_use) {
spin_unlock_bh(&logptr->priv_lock);
return -EBUSY;
- } else {
- logptr->dev_in_use = 1;
- spin_unlock_bh(&logptr->priv_lock);
}
-
+ logptr->dev_in_use = 1;
+ logptr->connection_established = 0;
+ logptr->iucv_path_severed = 0;
atomic_set(&logptr->receive_ready, 0);
logptr->buffer_free = 1;
+ spin_unlock_bh(&logptr->priv_lock);
/* set the file options */
filp->private_data = logptr;
filp->f_op = &vmlogrdr_fops;
/* start recording for this service*/
- ret=0;
- if (logptr->autorecording)
+ if (logptr->autorecording) {
ret = vmlogrdr_recording(logptr,1,logptr->autopurge);
- if (ret)
- printk (KERN_WARNING "vmlogrdr: failed to start "
- "recording automatically\n");
-
- /* Register with iucv driver */
- logptr->iucv_handle = iucv_register_program(iucvMagic,
- logptr->system_service, mask, &vmlogrdr_iucvops,
- logptr);
-
- if (logptr->iucv_handle == NULL) {
- printk (KERN_ERR "vmlogrdr: failed to register with"
- "iucv driver\n");
- goto not_registered;
+ if (ret)
+ printk (KERN_WARNING "vmlogrdr: failed to start "
+ "recording automatically\n");
}
/* create connection to the system service */
- spin_lock_bh(&logptr->priv_lock);
- logptr->connection_established = 0;
- logptr->iucv_path_severed = 0;
- spin_unlock_bh(&logptr->priv_lock);
-
- connect_rc = iucv_connect (&(logptr->pathid), 10, iucvMagic,
- logptr->system_service, iucv_host, 0,
- NULL, NULL,
- logptr->iucv_handle, NULL);
+ logptr->path = iucv_path_alloc(10, 0, GFP_KERNEL);
+ if (!logptr->path)
+ goto out_dev;
+ connect_rc = iucv_path_connect(logptr->path, &vmlogrdr_iucv_handler,
+ logptr->system_service, NULL, NULL,
+ logptr);
if (connect_rc) {
printk (KERN_ERR "vmlogrdr: iucv connection to %s "
"failed with rc %i \n", logptr->system_service,
connect_rc);
- goto not_connected;
+ goto out_path;
}
/* We've issued the connect and now we must wait for a
@@ -398,35 +363,28 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
*/
wait_event(conn_wait_queue, (logptr->connection_established)
|| (logptr->iucv_path_severed));
- if (logptr->iucv_path_severed) {
- goto not_connected;
- }
-
+ if (logptr->iucv_path_severed)
+ goto out_record;
return nonseekable_open(inode, filp);
-not_connected:
- iucv_unregister_program(logptr->iucv_handle);
- logptr->iucv_handle = NULL;
-not_registered:
+out_record:
if (logptr->autorecording)
vmlogrdr_recording(logptr,0,logptr->autopurge);
+out_path:
+ kfree(logptr->path); /* kfree(NULL) is ok. */
+ logptr->path = NULL;
+out_dev:
logptr->dev_in_use = 0;
return -EIO;
-
-
}
-static int
-vmlogrdr_release (struct inode *inode, struct file *filp)
+static int vmlogrdr_release (struct inode *inode, struct file *filp)
{
int ret;
struct vmlogrdr_priv_t * logptr = filp->private_data;
- iucv_unregister_program(logptr->iucv_handle);
- logptr->iucv_handle = NULL;
-
if (logptr->autorecording) {
ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
if (ret)
@@ -439,8 +397,8 @@ vmlogrdr_release (struct inode *inode, struct file *filp)
}
-static int
-vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
+static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv)
+{
int rc, *temp;
/* we need to keep track of two data sizes here:
* The number of bytes we need to receive from iucv and
@@ -461,8 +419,7 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
* We need to return the total length of the record
* + size of FENCE in the first 4 bytes of the buffer.
*/
- iucv_data_count =
- priv->local_interrupt_buffer.ln1msg2.ipbfln1f;
+ iucv_data_count = priv->local_interrupt_buffer.length;
user_data_count = sizeof(int);
temp = (int*)priv->buffer;
*temp= iucv_data_count + sizeof(FENCE);
@@ -474,14 +431,10 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
*/
if (iucv_data_count > NET_BUFFER_SIZE)
iucv_data_count = NET_BUFFER_SIZE;
- rc = iucv_receive(priv->pathid,
- priv->local_interrupt_buffer.ipmsgid,
- priv->local_interrupt_buffer.iptrgcls,
- buffer,
- iucv_data_count,
- NULL,
- NULL,
- &priv->residual_length);
+ rc = iucv_message_receive(priv->path,
+ &priv->local_interrupt_buffer,
+ 0, buffer, iucv_data_count,
+ &priv->residual_length);
spin_unlock_bh(&priv->priv_lock);
/* An rc of 5 indicates that the record was bigger then
* the buffer, which is OK for us. A 9 indicates that the
@@ -513,8 +466,8 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
}
-static ssize_t
-vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos)
+static ssize_t vmlogrdr_read(struct file *filp, char __user *data,
+ size_t count, loff_t * ppos)
{
int rc;
struct vmlogrdr_priv_t * priv = filp->private_data;
@@ -546,8 +499,10 @@ vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos)
return count;
}
-static ssize_t
-vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
+static ssize_t vmlogrdr_autopurge_store(struct device * dev,
+ struct device_attribute *attr,
+ const char * buf, size_t count)
+{
struct vmlogrdr_priv_t *priv = dev->driver_data;
ssize_t ret = count;
@@ -565,8 +520,10 @@ vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, con
}
-static ssize_t
-vmlogrdr_autopurge_show(struct device *dev, struct device_attribute *attr, char *buf) {
+static ssize_t vmlogrdr_autopurge_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
struct vmlogrdr_priv_t *priv = dev->driver_data;
return sprintf(buf, "%u\n", priv->autopurge);
}
@@ -576,8 +533,10 @@ static DEVICE_ATTR(autopurge, 0644, vmlogrdr_autopurge_show,
vmlogrdr_autopurge_store);
-static ssize_t
-vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
+static ssize_t vmlogrdr_purge_store(struct device * dev,
+ struct device_attribute *attr,
+ const char * buf, size_t count)
+{
char cp_command[80];
char cp_response[80];
@@ -617,9 +576,10 @@ vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const c
static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store);
-static ssize_t
-vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr, const char *buf,
- size_t count) {
+static ssize_t vmlogrdr_autorecording_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
struct vmlogrdr_priv_t *priv = dev->driver_data;
ssize_t ret = count;
@@ -637,8 +597,10 @@ vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr,
}
-static ssize_t
-vmlogrdr_autorecording_show(struct device *dev, struct device_attribute *attr, char *buf) {
+static ssize_t vmlogrdr_autorecording_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
struct vmlogrdr_priv_t *priv = dev->driver_data;
return sprintf(buf, "%u\n", priv->autorecording);
}
@@ -648,9 +610,10 @@ static DEVICE_ATTR(autorecording, 0644, vmlogrdr_autorecording_show,
vmlogrdr_autorecording_store);
-static ssize_t
-vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
-
+static ssize_t vmlogrdr_recording_store(struct device * dev,
+ struct device_attribute *attr,
+ const char * buf, size_t count)
+{
struct vmlogrdr_priv_t *priv = dev->driver_data;
ssize_t ret;
@@ -675,8 +638,9 @@ vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, con
static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store);
-static ssize_t
-vmlogrdr_recording_status_show(struct device_driver *driver, char *buf) {
+static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver,
+ char *buf)
+{
char cp_command[] = "QUERY RECORDING ";
int len;
@@ -709,52 +673,63 @@ static struct device_driver vmlogrdr_driver = {
};
-static int
-vmlogrdr_register_driver(void) {
+static int vmlogrdr_register_driver(void)
+{
int ret;
+ /* Register with iucv driver */
+ ret = iucv_register(&vmlogrdr_iucv_handler, 1);
+ if (ret) {
+ printk (KERN_ERR "vmlogrdr: failed to register with"
+ "iucv driver\n");
+ goto out;
+ }
+
ret = driver_register(&vmlogrdr_driver);
if (ret) {
printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
- return ret;
+ goto out_iucv;
}
ret = driver_create_file(&vmlogrdr_driver,
&driver_attr_recording_status);
if (ret) {
printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
- goto unregdriver;
+ goto out_driver;
}
vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
if (IS_ERR(vmlogrdr_class)) {
printk(KERN_ERR "vmlogrdr: failed to create class.\n");
- ret=PTR_ERR(vmlogrdr_class);
- vmlogrdr_class=NULL;
- goto unregattr;
+ ret = PTR_ERR(vmlogrdr_class);
+ vmlogrdr_class = NULL;
+ goto out_attr;
}
return 0;
-unregattr:
+out_attr:
driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
-unregdriver:
+out_driver:
driver_unregister(&vmlogrdr_driver);
+out_iucv:
+ iucv_unregister(&vmlogrdr_iucv_handler, 1);
+out:
return ret;
}
-static void
-vmlogrdr_unregister_driver(void) {
+static void vmlogrdr_unregister_driver(void)
+{
class_destroy(vmlogrdr_class);
vmlogrdr_class = NULL;
driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
driver_unregister(&vmlogrdr_driver);
- return;
+ iucv_unregister(&vmlogrdr_iucv_handler, 1);
}
-static int
-vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
+static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
+{
struct device *dev;
int ret;
@@ -803,9 +778,10 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
}
-static int
-vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
- class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
+static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
+{
+ class_device_destroy(vmlogrdr_class,
+ MKDEV(vmlogrdr_major, priv->minor_num));
if (priv->device != NULL) {
sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
device_unregister(priv->device);
@@ -815,8 +791,8 @@ vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
}
-static int
-vmlogrdr_register_cdev(dev_t dev) {
+static int vmlogrdr_register_cdev(dev_t dev)
+{
int rc = 0;
vmlogrdr_cdev = cdev_alloc();
if (!vmlogrdr_cdev) {
@@ -836,9 +812,10 @@ vmlogrdr_register_cdev(dev_t dev) {
}
-static void
-vmlogrdr_cleanup(void) {
+static void vmlogrdr_cleanup(void)
+{
int i;
+
if (vmlogrdr_cdev) {
cdev_del(vmlogrdr_cdev);
vmlogrdr_cdev=NULL;
@@ -855,8 +832,7 @@ vmlogrdr_cleanup(void) {
}
-static int
-vmlogrdr_init(void)
+static int vmlogrdr_init(void)
{
int rc;
int i;
@@ -906,8 +882,7 @@ cleanup:
}
-static void
-vmlogrdr_exit(void)
+static void vmlogrdr_exit(void)
{
vmlogrdr_cleanup();
printk (KERN_INFO "vmlogrdr: driver unloaded\n");
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 52625153a4f0..f98fa465df0a 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -22,13 +22,6 @@ config CTC
available. This option is also available as a module which will be
called ctc.ko. If you do not know what it is, it's safe to say "Y".
-config IUCV
- tristate "IUCV support (VM only)"
- help
- Select this option if you want to use inter-user communication
- under VM or VIF. If unsure, say "Y" to enable a fast communication
- link between VM guests.
-
config NETIUCV
tristate "IUCV network device support (VM only)"
depends on IUCV && NETDEVICES
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 4777e36a922f..bbe3ab2e93d9 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -4,7 +4,6 @@
ctc-objs := ctcmain.o ctcdbug.o
-obj-$(CONFIG_IUCV) += iucv.o
obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
deleted file mode 100644
index 229aeb5fc399..000000000000
--- a/drivers/s390/net/iucv.c
+++ /dev/null
@@ -1,2540 +0,0 @@
-/*
- * IUCV network driver
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s):
- * Original source:
- * Alan Altmark (Alan_Altmark@us.ibm.com) Sept. 2000
- * Xenia Tkatschow (xenia@us.ibm.com)
- * 2Gb awareness and general cleanup:
- * Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- *
- * Documentation used:
- * The original source
- * CP Programming Service, IBM document # SC24-5760
- *
- * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/* #define DEBUG */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <linux/spinlock.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <asm/atomic.h>
-#include "iucv.h"
-#include <asm/io.h>
-#include <asm/s390_ext.h>
-#include <asm/ebcdic.h>
-#include <asm/smp.h>
-#include <asm/s390_rdev.h>
-
-/* FLAGS:
- * All flags are defined in the field IPFLAGS1 of each function
- * and can be found in CP Programming Services.
- * IPSRCCLS - Indicates you have specified a source class
- * IPFGMCL - Indicates you have specified a target class
- * IPFGPID - Indicates you have specified a pathid
- * IPFGMID - Indicates you have specified a message ID
- * IPANSLST - Indicates that you are using an address list for
- * reply data
- * IPBUFLST - Indicates that you are using an address list for
- * message data
- */
-
-#define IPSRCCLS 0x01
-#define IPFGMCL 0x01
-#define IPFGPID 0x02
-#define IPFGMID 0x04
-#define IPANSLST 0x08
-#define IPBUFLST 0x40
-
-static int
-iucv_bus_match (struct device *dev, struct device_driver *drv)
-{
- return 0;
-}
-
-struct bus_type iucv_bus = {
- .name = "iucv",
- .match = iucv_bus_match,
-};
-
-struct device *iucv_root;
-
-/* General IUCV interrupt structure */
-typedef struct {
- __u16 ippathid;
- __u8 res1;
- __u8 iptype;
- __u32 res2;
- __u8 ipvmid[8];
- __u8 res3[24];
-} iucv_GeneralInterrupt;
-
-static iucv_GeneralInterrupt *iucv_external_int_buffer = NULL;
-
-/* Spin Lock declaration */
-
-static DEFINE_SPINLOCK(iucv_lock);
-
-static int messagesDisabled = 0;
-
-/***************INTERRUPT HANDLING ***************/
-
-typedef struct {
- struct list_head queue;
- iucv_GeneralInterrupt data;
-} iucv_irqdata;
-
-static struct list_head iucv_irq_queue;
-static DEFINE_SPINLOCK(iucv_irq_queue_lock);
-
-/*
- *Internal function prototypes
- */
-static void iucv_tasklet_handler(unsigned long);
-static void iucv_irq_handler(__u16);
-
-static DECLARE_TASKLET(iucv_tasklet,iucv_tasklet_handler,0);
-
-/************ FUNCTION ID'S ****************************/
-
-#define ACCEPT 10
-#define CONNECT 11
-#define DECLARE_BUFFER 12
-#define PURGE 9
-#define QUERY 0
-#define QUIESCE 13
-#define RECEIVE 5
-#define REJECT 8
-#define REPLY 6
-#define RESUME 14
-#define RETRIEVE_BUFFER 2
-#define SEND 4
-#define SETMASK 16
-#define SEVER 15
-
-/**
- * Structure: handler
- * members: list - list management.
- * structure: id
- * userid - 8 char array of machine identification
- * user_data - 16 char array for user identification
- * mask - 24 char array used to compare the 2 previous
- * interrupt_table - vector of interrupt functions.
- * pgm_data - ulong, application data that is passed
- * to the interrupt handlers
-*/
-typedef struct handler_t {
- struct list_head list;
- struct {
- __u8 userid[8];
- __u8 user_data[16];
- __u8 mask[24];
- } id;
- iucv_interrupt_ops_t *interrupt_table;
- void *pgm_data;
-} handler;
-
-/**
- * iucv_handler_table: List of registered handlers.
- */
-static struct list_head iucv_handler_table;
-
-/**
- * iucv_pathid_table: an array of *handler pointing into
- * iucv_handler_table for fast indexing by pathid;
- */
-static handler **iucv_pathid_table;
-
-static unsigned long max_connections;
-
-/**
- * iucv_cpuid: contains the logical cpu number of the cpu which
- * has declared the iucv buffer by issuing DECLARE_BUFFER.
- * If no cpu has done the initialization iucv_cpuid contains -1.
- */
-static int iucv_cpuid = -1;
-/**
- * register_flag: is 0 when external interrupt has not been registered
- */
-static int register_flag;
-
-/****************FIVE 40-BYTE PARAMETER STRUCTURES******************/
-/* Data struct 1: iparml_control
- * Used for iucv_accept
- * iucv_connect
- * iucv_quiesce
- * iucv_resume
- * iucv_sever
- * iucv_retrieve_buffer
- * Data struct 2: iparml_dpl (data in parameter list)
- * Used for iucv_send_prmmsg
- * iucv_send2way_prmmsg
- * iucv_send2way_prmmsg_array
- * iucv_reply_prmmsg
- * Data struct 3: iparml_db (data in a buffer)
- * Used for iucv_receive
- * iucv_receive_array
- * iucv_reject
- * iucv_reply
- * iucv_reply_array
- * iucv_send
- * iucv_send_array
- * iucv_send2way
- * iucv_send2way_array
- * iucv_declare_buffer
- * Data struct 4: iparml_purge
- * Used for iucv_purge
- * iucv_query
- * Data struct 5: iparml_set_mask
- * Used for iucv_set_mask
- */
-
-typedef struct {
- __u16 ippathid;
- __u8 ipflags1;
- __u8 iprcode;
- __u16 ipmsglim;
- __u16 res1;
- __u8 ipvmid[8];
- __u8 ipuser[16];
- __u8 iptarget[8];
-} iparml_control;
-
-typedef struct {
- __u16 ippathid;
- __u8 ipflags1;
- __u8 iprcode;
- __u32 ipmsgid;
- __u32 iptrgcls;
- __u8 iprmmsg[8];
- __u32 ipsrccls;
- __u32 ipmsgtag;
- __u32 ipbfadr2;
- __u32 ipbfln2f;
- __u32 res;
-} iparml_dpl;
-
-typedef struct {
- __u16 ippathid;
- __u8 ipflags1;
- __u8 iprcode;
- __u32 ipmsgid;
- __u32 iptrgcls;
- __u32 ipbfadr1;
- __u32 ipbfln1f;
- __u32 ipsrccls;
- __u32 ipmsgtag;
- __u32 ipbfadr2;
- __u32 ipbfln2f;
- __u32 res;
-} iparml_db;
-
-typedef struct {
- __u16 ippathid;
- __u8 ipflags1;
- __u8 iprcode;
- __u32 ipmsgid;
- __u8 ipaudit[3];
- __u8 res1[5];
- __u32 res2;
- __u32 ipsrccls;
- __u32 ipmsgtag;
- __u32 res3[3];
-} iparml_purge;
-
-typedef struct {
- __u8 ipmask;
- __u8 res1[2];
- __u8 iprcode;
- __u32 res2[9];
-} iparml_set_mask;
-
-typedef struct {
- union {
- iparml_control p_ctrl;
- iparml_dpl p_dpl;
- iparml_db p_db;
- iparml_purge p_purge;
- iparml_set_mask p_set_mask;
- } param;
- atomic_t in_use;
- __u32 res;
-} __attribute__ ((aligned(8))) iucv_param;
-#define PARAM_POOL_SIZE (PAGE_SIZE / sizeof(iucv_param))
-
-static iucv_param * iucv_param_pool;
-
-MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
-MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
-MODULE_LICENSE("GPL");
-
-/*
- * Debugging stuff
- *******************************************************************************/
-
-
-#ifdef DEBUG
-static int debuglevel = 0;
-
-module_param(debuglevel, int, 0);
-MODULE_PARM_DESC(debuglevel,
- "Specifies the debug level (0=off ... 3=all)");
-
-static void
-iucv_dumpit(char *title, void *buf, int len)
-{
- int i;
- __u8 *p = (__u8 *)buf;
-
- if (debuglevel < 3)
- return;
-
- printk(KERN_DEBUG "%s\n", title);
- printk(" ");
- for (i = 0; i < len; i++) {
- if (!(i % 16) && i != 0)
- printk ("\n ");
- else if (!(i % 4) && i != 0)
- printk(" ");
- printk("%02X", *p++);
- }
- if (len % 16)
- printk ("\n");
- return;
-}
-#define iucv_debug(lvl, fmt, args...) \
-do { \
- if (debuglevel >= lvl) \
- printk(KERN_DEBUG "%s: " fmt "\n", __FUNCTION__ , ## args); \
-} while (0)
-
-#else
-
-#define iucv_debug(lvl, fmt, args...) do { } while (0)
-#define iucv_dumpit(title, buf, len) do { } while (0)
-
-#endif
-
-/*
- * Internal functions
- *******************************************************************************/
-
-/**
- * print start banner
- */
-static void
-iucv_banner(void)
-{
- printk(KERN_INFO "IUCV lowlevel driver initialized\n");
-}
-
-/**
- * iucv_init - Initialization
- *
- * Allocates and initializes various data structures.
- */
-static int
-iucv_init(void)
-{
- int ret;
-
- if (iucv_external_int_buffer)
- return 0;
-
- if (!MACHINE_IS_VM) {
- printk(KERN_ERR "IUCV: IUCV connection needs VM as base\n");
- return -EPROTONOSUPPORT;
- }
-
- ret = bus_register(&iucv_bus);
- if (ret) {
- printk(KERN_ERR "IUCV: failed to register bus.\n");
- return ret;
- }
-
- iucv_root = s390_root_dev_register("iucv");
- if (IS_ERR(iucv_root)) {
- printk(KERN_ERR "IUCV: failed to register iucv root.\n");
- bus_unregister(&iucv_bus);
- return PTR_ERR(iucv_root);
- }
-
- /* Note: GFP_DMA used used to get memory below 2G */
- iucv_external_int_buffer = kzalloc(sizeof(iucv_GeneralInterrupt),
- GFP_KERNEL|GFP_DMA);
- if (!iucv_external_int_buffer) {
- printk(KERN_WARNING
- "%s: Could not allocate external interrupt buffer\n",
- __FUNCTION__);
- s390_root_dev_unregister(iucv_root);
- bus_unregister(&iucv_bus);
- return -ENOMEM;
- }
-
- /* Initialize parameter pool */
- iucv_param_pool = kzalloc(sizeof(iucv_param) * PARAM_POOL_SIZE,
- GFP_KERNEL|GFP_DMA);
- if (!iucv_param_pool) {
- printk(KERN_WARNING "%s: Could not allocate param pool\n",
- __FUNCTION__);
- kfree(iucv_external_int_buffer);
- iucv_external_int_buffer = NULL;
- s390_root_dev_unregister(iucv_root);
- bus_unregister(&iucv_bus);
- return -ENOMEM;
- }
-
- /* Initialize irq queue */
- INIT_LIST_HEAD(&iucv_irq_queue);
-
- /* Initialize handler table */
- INIT_LIST_HEAD(&iucv_handler_table);
-
- iucv_banner();
- return 0;
-}
-
-/**
- * iucv_exit - De-Initialization
- *
- * Frees everything allocated from iucv_init.
- */
-static int iucv_retrieve_buffer (void);
-
-static void
-iucv_exit(void)
-{
- iucv_retrieve_buffer();
- kfree(iucv_external_int_buffer);
- iucv_external_int_buffer = NULL;
- kfree(iucv_param_pool);
- iucv_param_pool = NULL;
- s390_root_dev_unregister(iucv_root);
- bus_unregister(&iucv_bus);
- printk(KERN_INFO "IUCV lowlevel driver unloaded\n");
-}
-
-/**
- * grab_param: - Get a parameter buffer from the pre-allocated pool.
- *
- * This function searches for an unused element in the pre-allocated pool
- * of parameter buffers. If one is found, it marks it "in use" and returns
- * a pointer to it. The calling function is responsible for releasing it
- * when it has finished its usage.
- *
- * Returns: A pointer to iucv_param.
- */
-static __inline__ iucv_param *
-grab_param(void)
-{
- iucv_param *ptr;
- static int hint = 0;
-
- ptr = iucv_param_pool + hint;
- do {
- ptr++;
- if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
- ptr = iucv_param_pool;
- } while (atomic_cmpxchg(&ptr->in_use, 0, 1) != 0);
- hint = ptr - iucv_param_pool;
-
- memset(&ptr->param, 0, sizeof(ptr->param));
- return ptr;
-}
-
-/**
- * release_param - Release a parameter buffer.
- * @p: A pointer to a struct iucv_param, previously obtained by calling
- * grab_param().
- *
- * This function marks the specified parameter buffer "unused".
- */
-static __inline__ void
-release_param(void *p)
-{
- atomic_set(&((iucv_param *)p)->in_use, 0);
-}
-
-/**
- * iucv_add_handler: - Add a new handler
- * @new_handler: handle that is being entered into chain.
- *
- * Places new handle on iucv_handler_table, if identical handler is not
- * found.
- *
- * Returns: 0 on success, !0 on failure (handler already in chain).
- */
-static int
-iucv_add_handler (handler *new)
-{
- ulong flags;
-
- iucv_debug(1, "entering");
- iucv_dumpit("handler:", new, sizeof(handler));
-
- spin_lock_irqsave (&iucv_lock, flags);
- if (!list_empty(&iucv_handler_table)) {
- struct list_head *lh;
-
- /**
- * Search list for handler with identical id. If one
- * is found, the new handler is _not_ added.
- */
- list_for_each(lh, &iucv_handler_table) {
- handler *h = list_entry(lh, handler, list);
- if (!memcmp(&new->id, &h->id, sizeof(h->id))) {
- iucv_debug(1, "ret 1");
- spin_unlock_irqrestore (&iucv_lock, flags);
- return 1;
- }
- }
- }
- /**
- * If we get here, no handler was found.
- */
- INIT_LIST_HEAD(&new->list);
- list_add(&new->list, &iucv_handler_table);
- spin_unlock_irqrestore (&iucv_lock, flags);
-
- iucv_debug(1, "exiting");
- return 0;
-}
-
-/**
- * b2f0:
- * @code: identifier of IUCV call to CP.
- * @parm: pointer to 40 byte iparml area passed to CP
- *
- * Calls CP to execute IUCV commands.
- *
- * Returns: return code from CP's IUCV call
- */
-static inline ulong b2f0(__u32 code, void *parm)
-{
- register unsigned long reg0 asm ("0");
- register unsigned long reg1 asm ("1");
- iucv_dumpit("iparml before b2f0 call:", parm, sizeof(iucv_param));
-
- reg0 = code;
- reg1 = virt_to_phys(parm);
- asm volatile(".long 0xb2f01000" : : "d" (reg0), "a" (reg1));
-
- iucv_dumpit("iparml after b2f0 call:", parm, sizeof(iucv_param));
-
- return (unsigned long)*((__u8 *)(parm + 3));
-}
-
-/*
- * Name: iucv_add_pathid
- * Purpose: Adds a path id to the system.
- * Input: pathid - pathid that is going to be entered into system
- * handle - address of handler that the pathid will be associated
- * with.
- * pgm_data - token passed in by application.
- * Output: 0: successful addition of pathid
- * - EINVAL - pathid entry is being used by another application
- * - ENOMEM - storage allocation for a new pathid table failed
-*/
-static int
-__iucv_add_pathid(__u16 pathid, handler *handler)
-{
-
- iucv_debug(1, "entering");
-
- iucv_debug(1, "handler is pointing to %p", handler);
-
- if (pathid > (max_connections - 1))
- return -EINVAL;
-
- if (iucv_pathid_table[pathid]) {
- iucv_debug(1, "pathid entry is %p", iucv_pathid_table[pathid]);
- printk(KERN_WARNING
- "%s: Pathid being used, error.\n", __FUNCTION__);
- return -EINVAL;
- }
- iucv_pathid_table[pathid] = handler;
-
- iucv_debug(1, "exiting");
- return 0;
-} /* end of add_pathid function */
-
-static int
-iucv_add_pathid(__u16 pathid, handler *handler)
-{
- ulong flags;
- int rc;
-
- spin_lock_irqsave (&iucv_lock, flags);
- rc = __iucv_add_pathid(pathid, handler);
- spin_unlock_irqrestore (&iucv_lock, flags);
- return rc;
-}
-
-static void
-iucv_remove_pathid(__u16 pathid)
-{
- ulong flags;
-
- if (pathid > (max_connections - 1))
- return;
-
- spin_lock_irqsave (&iucv_lock, flags);
- iucv_pathid_table[pathid] = NULL;
- spin_unlock_irqrestore (&iucv_lock, flags);
-}
-
-/**
- * iucv_declare_buffer_cpuid
- * Register at VM for subsequent IUCV operations. This is executed
- * on the reserved CPU iucv_cpuid. Called from iucv_declare_buffer().
- */
-static void
-iucv_declare_buffer_cpuid (void *result)
-{
- iparml_db *parm;
-
- parm = (iparml_db *)grab_param();
- parm->ipbfadr1 = virt_to_phys(iucv_external_int_buffer);
- if ((*((ulong *)result) = b2f0(DECLARE_BUFFER, parm)) == 1)
- *((ulong *)result) = parm->iprcode;
- release_param(parm);
-}
-
-/**
- * iucv_retrieve_buffer_cpuid:
- * Unregister IUCV usage at VM. This is always executed on the same
- * cpu that registered the buffer to VM.
- * Called from iucv_retrieve_buffer().
- */
-static void
-iucv_retrieve_buffer_cpuid (void *cpu)
-{
- iparml_control *parm;
-
- parm = (iparml_control *)grab_param();
- b2f0(RETRIEVE_BUFFER, parm);
- release_param(parm);
-}
-
-/**
- * Name: iucv_declare_buffer
- * Purpose: Specifies the guests real address of an external
- * interrupt.
- * Input: void
- * Output: iprcode - return code from b2f0 call
- */
-static int
-iucv_declare_buffer (void)
-{
- unsigned long flags;
- ulong b2f0_result;
-
- iucv_debug(1, "entering");
- b2f0_result = -ENODEV;
- spin_lock_irqsave (&iucv_lock, flags);
- if (iucv_cpuid == -1) {
- /* Reserve any cpu for use by iucv. */
- iucv_cpuid = smp_get_cpu(CPU_MASK_ALL);
- spin_unlock_irqrestore (&iucv_lock, flags);
- smp_call_function_on(iucv_declare_buffer_cpuid,
- &b2f0_result, 0, 1, iucv_cpuid);
- if (b2f0_result) {
- smp_put_cpu(iucv_cpuid);
- iucv_cpuid = -1;
- }
- iucv_debug(1, "Address of EIB = %p", iucv_external_int_buffer);
- } else {
- spin_unlock_irqrestore (&iucv_lock, flags);
- b2f0_result = 0;
- }
- iucv_debug(1, "exiting");
- return b2f0_result;
-}
-
-/**
- * iucv_retrieve_buffer:
- *
- * Terminates all use of IUCV.
- * Returns: return code from CP
- */
-static int
-iucv_retrieve_buffer (void)
-{
- iucv_debug(1, "entering");
- if (iucv_cpuid != -1) {
- smp_call_function_on(iucv_retrieve_buffer_cpuid,
- NULL, 0, 1, iucv_cpuid);
- /* Release the cpu reserved by iucv_declare_buffer. */
- smp_put_cpu(iucv_cpuid);
- iucv_cpuid = -1;
- }
- iucv_debug(1, "exiting");
- return 0;
-}
-
-/**
- * iucv_remove_handler:
- * @users_handler: handler to be removed
- *
- * Remove handler when application unregisters.
- */
-static void
-iucv_remove_handler(handler *handler)
-{
- unsigned long flags;
-
- if ((!iucv_pathid_table) || (!handler))
- return;
-
- iucv_debug(1, "entering");
-
- spin_lock_irqsave (&iucv_lock, flags);
- list_del(&handler->list);
- if (list_empty(&iucv_handler_table)) {
- if (register_flag) {
- unregister_external_interrupt(0x4000, iucv_irq_handler);
- register_flag = 0;
- }
- }
- spin_unlock_irqrestore (&iucv_lock, flags);
-
- iucv_debug(1, "exiting");
- return;
-}
-
-/**
- * iucv_register_program:
- * @pgmname: user identification
- * @userid: machine identification
- * @pgmmask: Indicates which bits in the pgmname and userid combined will be
- * used to determine who is given control.
- * @ops: Address of interrupt handler table.
- * @pgm_data: Application data to be passed to interrupt handlers.
- *
- * Registers an application with IUCV.
- * Returns:
- * The address of handler, or NULL on failure.
- * NOTE on pgmmask:
- * If pgmname, userid and pgmmask are provided, pgmmask is entered into the
- * handler as is.
- * If pgmmask is NULL, the internal mask is set to all 0xff's
- * When userid is NULL, the first 8 bytes of the internal mask are forced
- * to 0x00.
- * If pgmmask and userid are NULL, the first 8 bytes of the internal mask
- * are forced to 0x00 and the last 16 bytes to 0xff.
- */
-
-iucv_handle_t
-iucv_register_program (__u8 pgmname[16],
- __u8 userid[8],
- __u8 pgmmask[24],
- iucv_interrupt_ops_t * ops, void *pgm_data)
-{
- ulong rc = 0; /* return code from function calls */
- handler *new_handler;
-
- iucv_debug(1, "entering");
-
- if (ops == NULL) {
- /* interrupt table is not defined */
- printk(KERN_WARNING "%s: Interrupt table is not defined, "
- "exiting\n", __FUNCTION__);
- return NULL;
- }
- if (!pgmname) {
- printk(KERN_WARNING "%s: pgmname not provided\n", __FUNCTION__);
- return NULL;
- }
-
- /* Allocate handler entry */
- new_handler = kmalloc(sizeof(handler), GFP_ATOMIC);
- if (new_handler == NULL) {
- printk(KERN_WARNING "%s: storage allocation for new handler "
- "failed.\n", __FUNCTION__);
- return NULL;
- }
-
- if (!iucv_pathid_table) {
- if (iucv_init()) {
- kfree(new_handler);
- return NULL;
- }
-
- max_connections = iucv_query_maxconn();
- iucv_pathid_table = kcalloc(max_connections, sizeof(handler *),
- GFP_ATOMIC);
- if (iucv_pathid_table == NULL) {
- printk(KERN_WARNING "%s: iucv_pathid_table storage "
- "allocation failed\n", __FUNCTION__);
- kfree(new_handler);
- return NULL;
- }
- }
- memset(new_handler, 0, sizeof (handler));
- memcpy(new_handler->id.user_data, pgmname,
- sizeof (new_handler->id.user_data));
- if (userid) {
- memcpy (new_handler->id.userid, userid,
- sizeof (new_handler->id.userid));
- ASCEBC (new_handler->id.userid,
- sizeof (new_handler->id.userid));
- EBC_TOUPPER (new_handler->id.userid,
- sizeof (new_handler->id.userid));
-
- if (pgmmask) {
- memcpy (new_handler->id.mask, pgmmask,
- sizeof (new_handler->id.mask));
- } else {
- memset (new_handler->id.mask, 0xFF,
- sizeof (new_handler->id.mask));
- }
- } else {
- if (pgmmask) {
- memcpy (new_handler->id.mask, pgmmask,
- sizeof (new_handler->id.mask));
- } else {
- memset (new_handler->id.mask, 0xFF,
- sizeof (new_handler->id.mask));
- }
- memset (new_handler->id.userid, 0x00,
- sizeof (new_handler->id.userid));
- }
- /* fill in the rest of handler */
- new_handler->pgm_data = pgm_data;
- new_handler->interrupt_table = ops;
-
- /*
- * Check if someone else is registered with same pgmname, userid
- * and mask. If someone is already registered with same pgmname,
- * userid and mask, registration will fail and NULL will be returned
- * to the application.
- * If identical handler not found, then handler is added to list.
- */
- rc = iucv_add_handler(new_handler);
- if (rc) {
- printk(KERN_WARNING "%s: Someone already registered with same "
- "pgmname, userid, pgmmask\n", __FUNCTION__);
- kfree (new_handler);
- return NULL;
- }
-
- rc = iucv_declare_buffer();
- if (rc) {
- char *err = "Unknown";
- iucv_remove_handler(new_handler);
- kfree(new_handler);
- switch(rc) {
- case 0x03:
- err = "Directory error";
- break;
- case 0x0a:
- err = "Invalid length";
- break;
- case 0x13:
- err = "Buffer already exists";
- break;
- case 0x3e:
- err = "Buffer overlap";
- break;
- case 0x5c:
- err = "Paging or storage error";
- break;
- }
- printk(KERN_WARNING "%s: iucv_declare_buffer "
- "returned error 0x%02lx (%s)\n", __FUNCTION__, rc, err);
- return NULL;
- }
- if (!register_flag) {
- /* request the 0x4000 external interrupt */
- rc = register_external_interrupt (0x4000, iucv_irq_handler);
- if (rc) {
- iucv_remove_handler(new_handler);
- kfree (new_handler);
- printk(KERN_WARNING "%s: "
- "register_external_interrupt returned %ld\n",
- __FUNCTION__, rc);
- return NULL;
-
- }
- register_flag = 1;
- }
- iucv_debug(1, "exiting");
- return new_handler;
-} /* end of register function */
-
-/**
- * iucv_unregister_program:
- * @handle: address of handler
- *
- * Unregister application with IUCV.
- * Returns:
- * 0 on success, -EINVAL, if specified handle is invalid.
- */
-
-int
-iucv_unregister_program (iucv_handle_t handle)
-{
- handler *h = NULL;
- struct list_head *lh;
- int i;
- ulong flags;
-
- iucv_debug(1, "entering");
- iucv_debug(1, "address of handler is %p", h);
-
- /* Checking if handle is valid */
- spin_lock_irqsave (&iucv_lock, flags);
- list_for_each(lh, &iucv_handler_table) {
- if ((handler *)handle == list_entry(lh, handler, list)) {
- h = (handler *)handle;
- break;
- }
- }
- if (!h) {
- spin_unlock_irqrestore (&iucv_lock, flags);
- if (handle)
- printk(KERN_WARNING
- "%s: Handler not found in iucv_handler_table.\n",
- __FUNCTION__);
- else
- printk(KERN_WARNING
- "%s: NULL handle passed by application.\n",
- __FUNCTION__);
- return -EINVAL;
- }
-
- /**
- * First, walk thru iucv_pathid_table and sever any pathid which is
- * still pointing to the handler to be removed.
- */
- for (i = 0; i < max_connections; i++)
- if (iucv_pathid_table[i] == h) {
- spin_unlock_irqrestore (&iucv_lock, flags);
- iucv_sever(i, h->id.user_data);
- spin_lock_irqsave(&iucv_lock, flags);
- }
- spin_unlock_irqrestore (&iucv_lock, flags);
-
- iucv_remove_handler(h);
- kfree(h);
-
- iucv_debug(1, "exiting");
- return 0;
-}
-
-/**
- * iucv_accept:
- * @pathid: Path identification number
- * @msglim_reqstd: The number of outstanding messages requested.
- * @user_data: Data specified by the iucv_connect function.
- * @flags1: Contains options for this path.
- * - IPPRTY (0x20) Specifies if you want to send priority message.
- * - IPRMDATA (0x80) Specifies whether your program can handle a message
- * in the parameter list.
- * - IPQUSCE (0x40) Specifies whether you want to quiesce the path being
- * established.
- * @handle: Address of handler.
- * @pgm_data: Application data passed to interrupt handlers.
- * @flags1_out: Pointer to an int. If not NULL, on return the options for
- * the path are stored at the given location:
- * - IPPRTY (0x20) Indicates you may send a priority message.
- * @msglim: Pointer to an __u16. If not NULL, on return the maximum
- * number of outstanding messages is stored at the given
- * location.
- *
- * This function is issued after the user receives a Connection Pending external
- * interrupt and now wishes to complete the IUCV communication path.
- * Returns:
- * return code from CP
- */
-int
-iucv_accept(__u16 pathid, __u16 msglim_reqstd,
- __u8 user_data[16], int flags1,
- iucv_handle_t handle, void *pgm_data,
- int *flags1_out, __u16 * msglim)
-{
- ulong b2f0_result = 0;
- ulong flags;
- struct list_head *lh;
- handler *h = NULL;
- iparml_control *parm;
-
- iucv_debug(1, "entering");
- iucv_debug(1, "pathid = %d", pathid);
-
- /* Checking if handle is valid */
- spin_lock_irqsave (&iucv_lock, flags);
- list_for_each(lh, &iucv_handler_table) {
- if ((handler *)handle == list_entry(lh, handler, list)) {
- h = (handler *)handle;
- break;
- }
- }
- spin_unlock_irqrestore (&iucv_lock, flags);
-
- if (!h) {
- if (handle)
- printk(KERN_WARNING
- "%s: Handler not found in iucv_handler_table.\n",
- __FUNCTION__);
- else
- printk(KERN_WARNING
- "%s: NULL handle passed by application.\n",
- __FUNCTION__);
- return -EINVAL;
- }
-
- parm = (iparml_control *)grab_param();
-
- parm->ippathid = pathid;
- parm->ipmsglim = msglim_reqstd;
- if (user_data)
- memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-
- parm->ipflags1 = (__u8)flags1;
- b2f0_result = b2f0(ACCEPT, parm);
-
- if (!b2f0_result) {
- if (msglim)
- *msglim = parm->ipmsglim;
- if (pgm_data)
- h->pgm_data = pgm_data;
- if (flags1_out)
- *flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
- }
- release_param(parm);
-
- iucv_debug(1, "exiting");
- return b2f0_result;
-}
-
-/**
- * iucv_connect:
- * @pathid: Path identification number
- * @msglim_reqstd: Number of outstanding messages requested
- * @user_data: 16-byte user data
- * @userid: 8-byte of user identification
- * @system_name: 8-byte identifying the system name
- * @flags1: Specifies options for this path:
- * - IPPRTY (0x20) Specifies if you want to send priority message.
- * - IPRMDATA (0x80) Specifies whether your program can handle a message
- * in the parameter list.
- * - IPQUSCE (0x40) Specifies whether you want to quiesce the path being
- * established.
- * - IPLOCAL (0x01) Allows an application to force the partner to be on the
- * local system. If local is specified then target class
- * cannot be specified.
- * @flags1_out: Pointer to an int. If not NULL, on return the options for
- * the path are stored at the given location:
- * - IPPRTY (0x20) Indicates you may send a priority message.
- * @msglim: Pointer to an __u16. If not NULL, on return the maximum
- * number of outstanding messages is stored at the given
- * location.
- * @handle: Address of handler.
- * @pgm_data: Application data to be passed to interrupt handlers.
- *
- * This function establishes an IUCV path. Although the connect may complete
- * successfully, you are not able to use the path until you receive an IUCV
- * Connection Complete external interrupt.
- * Returns: return code from CP, or one of the following
- * - ENOMEM
- * - return code from iucv_declare_buffer
- * - EINVAL - invalid handle passed by application
- * - EINVAL - pathid address is NULL
- * - ENOMEM - pathid table storage allocation failed
- * - return code from internal function add_pathid
- */
-int
-iucv_connect (__u16 *pathid, __u16 msglim_reqstd,
- __u8 user_data[16], __u8 userid[8],
- __u8 system_name[8], int flags1,
- int *flags1_out, __u16 * msglim,
- iucv_handle_t handle, void *pgm_data)
-{
- iparml_control *parm;
- iparml_control local_parm;
- struct list_head *lh;
- ulong b2f0_result = 0;
- ulong flags;
- int add_pathid_result = 0;
- handler *h = NULL;
- __u8 no_memory[16] = "NO MEMORY";
-
- iucv_debug(1, "entering");
-
- /* Checking if handle is valid */
- spin_lock_irqsave (&iucv_lock, flags);
- list_for_each(lh, &iucv_handler_table) {
- if ((handler *)handle == list_entry(lh, handler, list)) {
- h = (handler *)handle;
- break;
- }
- }
- spin_unlock_irqrestore (&iucv_lock, flags);
-
- if (!h) {
- if (handle)
- printk(KERN_WARNING
- "%s: Handler not found in iucv_handler_table.\n",
- __FUNCTION__);
- else
- printk(KERN_WARNING
- "%s: NULL handle passed by application.\n",
- __FUNCTION__);
- return -EINVAL;
- }
-
- if (pathid == NULL) {
- printk(KERN_WARNING "%s: NULL pathid pointer\n",
- __FUNCTION__);
- return -EINVAL;
- }
-
- parm = (iparml_control *)grab_param();
-
- parm->ipmsglim = msglim_reqstd;
-
- if (user_data)
- memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-
- if (userid) {
- memcpy(parm->ipvmid, userid, sizeof(parm->ipvmid));
- ASCEBC(parm->ipvmid, sizeof(parm->ipvmid));
- EBC_TOUPPER(parm->ipvmid, sizeof(parm->ipvmid));
- }
-
- if (system_name) {
- memcpy(parm->iptarget, system_name, sizeof(parm->iptarget));
- ASCEBC(parm->iptarget, sizeof(parm->iptarget));
- EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget));
- }
-
- /* In order to establish an IUCV connection, the procedure is:
- *
- * b2f0(CONNECT)
- * take the ippathid from the b2f0 call
- * register the handler to the ippathid
- *
- * Unfortunately, the ConnectionEstablished message gets sent after the
- * b2f0(CONNECT) call but before the register is handled.
- *
- * In order for this race condition to be eliminated, the IUCV Control
- * Interrupts must be disabled for the above procedure.
- *
- * David Kennedy <dkennedy@linuxcare.com>
- */
-
- /* Enable everything but IUCV Control messages */
- iucv_setmask(~(AllInterrupts));
- messagesDisabled = 1;
-
- spin_lock_irqsave (&iucv_lock, flags);
- parm->ipflags1 = (__u8)flags1;
- b2f0_result = b2f0(CONNECT, parm);
- memcpy(&local_parm, parm, sizeof(local_parm));
- release_param(parm);
- parm = &local_parm;
- if (!b2f0_result)
- add_pathid_result = __iucv_add_pathid(parm->ippathid, h);
- spin_unlock_irqrestore (&iucv_lock, flags);
-
- if (b2f0_result) {
- iucv_setmask(~0);
- messagesDisabled = 0;
- return b2f0_result;
- }
-
- *pathid = parm->ippathid;
-
- /* Enable everything again */
- iucv_setmask(IUCVControlInterruptsFlag);
-
- if (msglim)
- *msglim = parm->ipmsglim;
- if (flags1_out)
- *flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
-
- if (add_pathid_result) {
- iucv_sever(*pathid, no_memory);
- printk(KERN_WARNING "%s: add_pathid failed with rc ="
- " %d\n", __FUNCTION__, add_pathid_result);
- return(add_pathid_result);
- }
-
- iucv_debug(1, "exiting");
- return b2f0_result;
-}
-
-/**
- * iucv_purge:
- * @pathid: Path identification number
- * @msgid: Message ID of message to purge.
- * @srccls: Message class of the message to purge.
- * @audit: Pointer to an __u32. If not NULL, on return, information about
- * asynchronous errors that may have affected the normal completion
- * of this message ist stored at the given location.
- *
- * Cancels a message you have sent.
- * Returns: return code from CP
- */
-int
-iucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit)
-{
- iparml_purge *parm;
- ulong b2f0_result = 0;
-
- iucv_debug(1, "entering");
- iucv_debug(1, "pathid = %d", pathid);
-
- parm = (iparml_purge *)grab_param();
-
- parm->ipmsgid = msgid;
- parm->ippathid = pathid;
- parm->ipsrccls = srccls;
- parm->ipflags1 |= (IPSRCCLS | IPFGMID | IPFGPID);
- b2f0_result = b2f0(PURGE, parm);
-
- if (!b2f0_result && audit) {
- memcpy(audit, parm->ipaudit, sizeof(parm->ipaudit));
- /* parm->ipaudit has only 3 bytes */
- *audit >>= 8;
- }
-
- release_param(parm);
-
- iucv_debug(1, "b2f0_result = %ld", b2f0_result);
- iucv_debug(1, "exiting");
- return b2f0_result;
-}
-
-/**
- * iucv_query_generic:
- * @want_maxconn: Flag, describing which value is to be returned.
- *
- * Helper function for iucv_query_maxconn() and iucv_query_bufsize().
- *
- * Returns: The buffersize, if want_maxconn is 0; the maximum number of
- * connections, if want_maxconn is 1 or an error-code < 0 on failure.
- */
-static int
-iucv_query_generic(int want_maxconn)
-{
- register unsigned long reg0 asm ("0");
- register unsigned long reg1 asm ("1");
- iparml_purge *parm = (iparml_purge *)grab_param();
- int bufsize, maxconn;
- int ccode;
-
- /**
- * Call b2f0 and store R0 (max buffer size),
- * R1 (max connections) and CC.
- */
- reg0 = QUERY;
- reg1 = virt_to_phys(parm);
- asm volatile(
- " .long 0xb2f01000\n"
- " ipm %0\n"
- " srl %0,28\n"
- : "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
- bufsize = reg0;
- maxconn = reg1;
- release_param(parm);
-
- if (ccode)
- return -EPERM;
- if (want_maxconn)
- return maxconn;
- return bufsize;
-}
-
-/**
- * iucv_query_maxconn:
- *
- * Determines the maximum number of connections thay may be established.
- *
- * Returns: Maximum number of connections that can be.
- */
-ulong
-iucv_query_maxconn(void)
-{
- return iucv_query_generic(1);
-}
-
-/**
- * iucv_query_bufsize:
- *
- * Determines the size of the external interrupt buffer.
- *
- * Returns: Size of external interrupt buffer.
- */
-ulong
-iucv_query_bufsize (void)
-{
- return iucv_query_generic(0);
-}
-
-/**
- * iucv_quiesce:
- * @pathid: Path identification number
- * @user_data: 16-byte user data
- *
- * Temporarily suspends incoming messages on an IUCV path.
- * You can later reactivate the path by invoking the iucv_resume function.
- * Returns: return code from CP
- */
-int
-iucv_quiesce (__u16 pathid, __u8 user_data[16])
-{
- iparml_control *parm;
- ulong b2f0_result = 0;
-
- iucv_debug(1, "entering");
- iucv_debug(1, "pathid = %d", pathid);
-
- parm = (iparml_control *)grab_param();
-
- memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
- parm->ippathid = pathid;
-
- b2f0_result = b2f0(QUIESCE, parm);
- release_param(parm);
-
- iucv_debug(1, "b2f0_result = %ld", b2f0_result);
- iucv_debug(1, "exiting");
-
- return b2f0_result;
-}
-
-/**
- * iucv_receive:
- * @pathid: Path identification number.
- * @buffer: Address of buffer to receive. Must be below 2G.
- * @buflen: Length of buffer to receive.
- * @msgid: Specifies the message ID.
- * @trgcls: Specifies target class.
- * @flags1_out: Receives options for path on return.
- * - IPNORPY (0x10) Specifies whether a reply is required
- * - IPPRTY (0x20) Specifies if you want to send priority message
- * - IPRMDATA (0x80) Specifies the data is contained in the parameter list
- * @residual_buffer: Receives the address of buffer updated by the number
- * of bytes you have received on return.
- * @residual_length: On return, receives one of the following values:
- * - 0 If the receive buffer is the same length as
- * the message.
- * - Remaining bytes in buffer If the receive buffer is longer than the
- * message.
- * - Remaining bytes in message If the receive buffer is shorter than the
- * message.
- *
- * This function receives messages that are being sent to you over established
- * paths.
- * Returns: return code from CP IUCV call; If the receive buffer is shorter
- * than the message, always 5
- * -EINVAL - buffer address is pointing to NULL
- */
-int
-iucv_receive (__u16 pathid, __u32 msgid, __u32 trgcls,
- void *buffer, ulong buflen,
- int *flags1_out, ulong * residual_buffer, ulong * residual_length)
-{
- iparml_db *parm;
- ulong b2f0_result;
- int moved = 0; /* number of bytes moved from parmlist to buffer */
-
- iucv_debug(2, "entering");
-
- if (!buffer)
- return -EINVAL;
-
- parm = (iparml_db *)grab_param();
-
- parm->ipbfadr1 = (__u32) (addr_t) buffer;
- parm->ipbfln1f = (__u32) ((ulong) buflen);
- parm->ipmsgid = msgid;
- parm->ippathid = pathid;
- parm->iptrgcls = trgcls;
- parm->ipflags1 = (IPFGPID | IPFGMID | IPFGMCL);
-
- b2f0_result = b2f0(RECEIVE, parm);
-
- if (!b2f0_result || b2f0_result == 5) {
- if (flags1_out) {
- iucv_debug(2, "*flags1_out = %d", *flags1_out);
- *flags1_out = (parm->ipflags1 & (~0x07));
- iucv_debug(2, "*flags1_out = %d", *flags1_out);
- }
-
- if (!(parm->ipflags1 & IPRMDATA)) { /*msg not in parmlist */
- if (residual_length)
- *residual_length = parm->ipbfln1f;
-
- if (residual_buffer)
- *residual_buffer = parm->ipbfadr1;
- } else {
- moved = min_t (unsigned long, buflen, 8);
-
- memcpy ((char *) buffer,
- (char *) &parm->ipbfadr1, moved);
-
- if (buflen < 8)
- b2f0_result = 5;
-
- if (residual_length)
- *residual_length = abs (buflen - 8);
-
- if (residual_buffer)
- *residual_buffer = (ulong) (buffer + moved);
- }
- }
- release_param(parm);
-
- iucv_debug(2, "exiting");
- return b2f0_result;
-}
-
-/*
- * Name: iucv_receive_array
- * Purpose: This function receives messages that are being sent to you
- * over established paths.
- * Input: pathid - path identification number
- * buffer - address of array of buffers
- * buflen - total length of buffers
- * msgid - specifies the message ID.
- * trgcls - specifies target class
- * Output:
- * flags1_out: Options for path.
- * IPNORPY - 0x10 specifies whether a reply is required
- * IPPRTY - 0x20 specifies if you want to send priority message
- * IPRMDATA - 0x80 specifies the data is contained in the parameter list
- * residual_buffer - address points to the current list entry IUCV
- * is working on.
- * residual_length -
- * Contains one of the following values, if the receive buffer is:
- * The same length as the message, this field is zero.
- * Longer than the message, this field contains the number of
- * bytes remaining in the buffer.
- * Shorter than the message, this field contains the residual
- * count (that is, the number of bytes remaining in the
- * message that does not fit into the buffer. In this case
- * b2f0_result = 5.
- * Return: b2f0_result - return code from CP
- * (-EINVAL) - buffer address is NULL
- */
-int
-iucv_receive_array (__u16 pathid,
- __u32 msgid, __u32 trgcls,
- iucv_array_t * buffer, ulong buflen,
- int *flags1_out,
- ulong * residual_buffer, ulong * residual_length)
-{
- iparml_db *parm;
- ulong b2f0_result;
- int i = 0, moved = 0, need_to_move = 8, dyn_len;
-
- iucv_debug(2, "entering");
-
- if (!buffer)
- return -EINVAL;
-
- parm = (iparml_db *)grab_param();
-
- parm->ipbfadr1 = (__u32) ((ulong) buffer);
- parm->ipbfln1f = (__u32) buflen;
- parm->ipmsgid = msgid;
- parm->ippathid = pathid;
- parm->iptrgcls = trgcls;
- parm->ipflags1 = (IPBUFLST | IPFGPID | IPFGMID | IPFGMCL);
-
- b2f0_result = b2f0(RECEIVE, parm);
-
- if (!b2f0_result || b2f0_result == 5) {
-
- if (flags1_out) {
- iucv_debug(2, "*flags1_out = %d", *flags1_out);
- *flags1_out = (parm->ipflags1 & (~0x07));
- iucv_debug(2, "*flags1_out = %d", *flags1_out);
- }
-
- if (!(parm->ipflags1 & IPRMDATA)) { /*msg not in parmlist */
-
- if (residual_length)
- *residual_length = parm->ipbfln1f;
-
- if (residual_buffer)
- *residual_buffer = parm->ipbfadr1;
-
- } else {
- /* copy msg from parmlist to users array. */
-
- while ((moved < 8) && (moved < buflen)) {
- dyn_len =
- min_t (unsigned int,
- (buffer + i)->length, need_to_move);
-
- memcpy ((char *)((ulong)((buffer + i)->address)),
- ((char *) &parm->ipbfadr1) + moved,
- dyn_len);
-
- moved += dyn_len;
- need_to_move -= dyn_len;
-
- (buffer + i)->address =
- (__u32)
- ((ulong)(__u8 *) ((ulong)(buffer + i)->address)
- + dyn_len);
-
- (buffer + i)->length -= dyn_len;
- i++;
- }
-
- if (need_to_move) /* buflen < 8 bytes */
- b2f0_result = 5;
-
- if (residual_length)
- *residual_length = abs (buflen - 8);
-
- if (residual_buffer) {
- if (!moved)
- *residual_buffer = (ulong) buffer;
- else
- *residual_buffer =
- (ulong) (buffer + (i - 1));
- }
-
- }
- }
- release_param(parm);
-
- iucv_debug(2, "exiting");
- return b2f0_result;
-}
-
-/**
- * iucv_reject:
- * @pathid: Path identification number.
- * @msgid: Message ID of the message to reject.
- * @trgcls: Target class of the message to reject.
- * Returns: return code from CP
- *
- * Refuses a specified message. Between the time you are notified of a
- * message and the time that you complete the message, the message may
- * be rejected.
- */
-int
-iucv_reject (__u16 pathid, __u32 msgid, __u32 trgcls)
-{
- iparml_db *parm;
- ulong b2f0_result = 0;
-
- iucv_debug(1, "entering");
- iucv_debug(1, "pathid = %d", pathid);
-
- parm = (iparml_db *)grab_param();
-
- parm->ippathid = pathid;
- parm->ipmsgid = msgid;
- parm->iptrgcls = trgcls;
- parm->ipflags1 = (IPFGMCL | IPFGMID | IPFGPID);
-
- b2f0_result = b2f0(REJECT, parm);
- release_param(parm);
-
- iucv_debug(1, "b2f0_result = %ld", b2f0_result);
- iucv_debug(1, "exiting");
-
- return b2f0_result;
-}
-
-/*
- * Name: iucv_reply
- * Purpose: This function responds to the two-way messages that you
- * receive. You must identify completely the message to
- * which you wish to reply. ie, pathid, msgid, and trgcls.
- * Input: pathid - path identification number
- * msgid - specifies the message ID.
- * trgcls - specifies target class
- * flags1 - option for path
- * IPPRTY- 0x20 - specifies if you want to send priority message
- * buffer - address of reply buffer
- * buflen - length of reply buffer
- * Output: ipbfadr2 - Address of buffer updated by the number
- * of bytes you have moved.
- * ipbfln2f - Contains one of the following values:
- * If the answer buffer is the same length as the reply, this field
- * contains zero.
- * If the answer buffer is longer than the reply, this field contains
- * the number of bytes remaining in the buffer.
- * If the answer buffer is shorter than the reply, this field contains
- * a residual count (that is, the number of bytes remianing in the
- * reply that does not fit into the buffer. In this
- * case b2f0_result = 5.
- * Return: b2f0_result - return code from CP
- * (-EINVAL) - buffer address is NULL
- */
-int
-iucv_reply (__u16 pathid,
- __u32 msgid, __u32 trgcls,
- int flags1,
- void *buffer, ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
-{
- iparml_db *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- if (!buffer)
- return -EINVAL;
-
- parm = (iparml_db *)grab_param();
-
- parm->ipbfadr2 = (__u32) ((ulong) buffer);
- parm->ipbfln2f = (__u32) buflen; /* length of message */
- parm->ippathid = pathid;
- parm->ipmsgid = msgid;
- parm->iptrgcls = trgcls;
- parm->ipflags1 = (__u8) flags1; /* priority message */
-
- b2f0_result = b2f0(REPLY, parm);
-
- if ((!b2f0_result) || (b2f0_result == 5)) {
- if (ipbfadr2)
- *ipbfadr2 = parm->ipbfadr2;
- if (ipbfln2f)
- *ipbfln2f = parm->ipbfln2f;
- }
- release_param(parm);
-
- iucv_debug(2, "exiting");
-
- return b2f0_result;
-}
-
-/*
- * Name: iucv_reply_array
- * Purpose: This function responds to the two-way messages that you
- * receive. You must identify completely the message to
- * which you wish to reply. ie, pathid, msgid, and trgcls.
- * The array identifies a list of addresses and lengths of
- * discontiguous buffers that contains the reply data.
- * Input: pathid - path identification number
- * msgid - specifies the message ID.
- * trgcls - specifies target class
- * flags1 - option for path
- * IPPRTY- specifies if you want to send priority message
- * buffer - address of array of reply buffers
- * buflen - total length of reply buffers
- * Output: ipbfadr2 - Address of buffer which IUCV is currently working on.
- * ipbfln2f - Contains one of the following values:
- * If the answer buffer is the same length as the reply, this field
- * contains zero.
- * If the answer buffer is longer than the reply, this field contains
- * the number of bytes remaining in the buffer.
- * If the answer buffer is shorter than the reply, this field contains
- * a residual count (that is, the number of bytes remianing in the
- * reply that does not fit into the buffer. In this
- * case b2f0_result = 5.
- * Return: b2f0_result - return code from CP
- * (-EINVAL) - buffer address is NULL
-*/
-int
-iucv_reply_array (__u16 pathid,
- __u32 msgid, __u32 trgcls,
- int flags1,
- iucv_array_t * buffer,
- ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
-{
- iparml_db *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- if (!buffer)
- return -EINVAL;
-
- parm = (iparml_db *)grab_param();
-
- parm->ipbfadr2 = (__u32) ((ulong) buffer);
- parm->ipbfln2f = buflen; /* length of message */
- parm->ippathid = pathid;
- parm->ipmsgid = msgid;
- parm->iptrgcls = trgcls;
- parm->ipflags1 = (IPANSLST | flags1);
-
- b2f0_result = b2f0(REPLY, parm);
-
- if ((!b2f0_result) || (b2f0_result == 5)) {
-
- if (ipbfadr2)
- *ipbfadr2 = parm->ipbfadr2;
- if (ipbfln2f)
- *ipbfln2f = parm->ipbfln2f;
- }
- release_param(parm);
-
- iucv_debug(2, "exiting");
-
- return b2f0_result;
-}
-
-/*
- * Name: iucv_reply_prmmsg
- * Purpose: This function responds to the two-way messages that you
- * receive. You must identify completely the message to
- * which you wish to reply. ie, pathid, msgid, and trgcls.
- * Prmmsg signifies the data is moved into the
- * parameter list.
- * Input: pathid - path identification number
- * msgid - specifies the message ID.
- * trgcls - specifies target class
- * flags1 - option for path
- * IPPRTY- specifies if you want to send priority message
- * prmmsg - 8-bytes of data to be placed into the parameter
- * list.
- * Output: NA
- * Return: b2f0_result - return code from CP
-*/
-int
-iucv_reply_prmmsg (__u16 pathid,
- __u32 msgid, __u32 trgcls, int flags1, __u8 prmmsg[8])
-{
- iparml_dpl *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- parm = (iparml_dpl *)grab_param();
-
- parm->ippathid = pathid;
- parm->ipmsgid = msgid;
- parm->iptrgcls = trgcls;
- memcpy(parm->iprmmsg, prmmsg, sizeof (parm->iprmmsg));
- parm->ipflags1 = (IPRMDATA | flags1);
-
- b2f0_result = b2f0(REPLY, parm);
- release_param(parm);
-
- iucv_debug(2, "exiting");
-
- return b2f0_result;
-}
-
-/**
- * iucv_resume:
- * @pathid: Path identification number
- * @user_data: 16-byte of user data
- *
- * This function restores communication over a quiesced path.
- * Returns: return code from CP
- */
-int
-iucv_resume (__u16 pathid, __u8 user_data[16])
-{
- iparml_control *parm;
- ulong b2f0_result = 0;
-
- iucv_debug(1, "entering");
- iucv_debug(1, "pathid = %d", pathid);
-
- parm = (iparml_control *)grab_param();
-
- memcpy (parm->ipuser, user_data, sizeof (*user_data));
- parm->ippathid = pathid;
-
- b2f0_result = b2f0(RESUME, parm);
- release_param(parm);
-
- iucv_debug(1, "exiting");
-
- return b2f0_result;
-}
-
-/*
- * Name: iucv_send
- * Purpose: sends messages
- * Input: pathid - ushort, pathid
- * msgid - ulong *, id of message returned to caller
- * trgcls - ulong, target message class
- * srccls - ulong, source message class
- * msgtag - ulong, message tag
- * flags1 - Contains options for this path.
- * IPPRTY - Ox20 - specifies if you want to send a priority message.
- * buffer - pointer to buffer
- * buflen - ulong, length of buffer
- * Output: b2f0_result - return code from b2f0 call
- * msgid - returns message id
- */
-int
-iucv_send (__u16 pathid, __u32 * msgid,
- __u32 trgcls, __u32 srccls,
- __u32 msgtag, int flags1, void *buffer, ulong buflen)
-{
- iparml_db *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- if (!buffer)
- return -EINVAL;
-
- parm = (iparml_db *)grab_param();
-
- parm->ipbfadr1 = (__u32) ((ulong) buffer);
- parm->ippathid = pathid;
- parm->iptrgcls = trgcls;
- parm->ipbfln1f = (__u32) buflen; /* length of message */
- parm->ipsrccls = srccls;
- parm->ipmsgtag = msgtag;
- parm->ipflags1 = (IPNORPY | flags1); /* one way priority message */
-
- b2f0_result = b2f0(SEND, parm);
-
- if ((!b2f0_result) && (msgid))
- *msgid = parm->ipmsgid;
- release_param(parm);
-
- iucv_debug(2, "exiting");
-
- return b2f0_result;
-}
-
-/*
- * Name: iucv_send_array
- * Purpose: This function transmits data to another application.
- * The contents of buffer is the address of the array of
- * addresses and lengths of discontiguous buffers that hold
- * the message text. This is a one-way message and the
- * receiver will not reply to the message.
- * Input: pathid - path identification number
- * trgcls - specifies target class
- * srccls - specifies the source message class
- * msgtag - specifies a tag to be associated witht the message
- * flags1 - option for path
- * IPPRTY- specifies if you want to send priority message
- * buffer - address of array of send buffers
- * buflen - total length of send buffers
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- * (-EINVAL) - buffer address is NULL
- */
-int
-iucv_send_array (__u16 pathid,
- __u32 * msgid,
- __u32 trgcls,
- __u32 srccls,
- __u32 msgtag, int flags1, iucv_array_t * buffer, ulong buflen)
-{
- iparml_db *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- if (!buffer)
- return -EINVAL;
-
- parm = (iparml_db *)grab_param();
-
- parm->ippathid = pathid;
- parm->iptrgcls = trgcls;
- parm->ipbfadr1 = (__u32) ((ulong) buffer);
- parm->ipbfln1f = (__u32) buflen; /* length of message */
- parm->ipsrccls = srccls;
- parm->ipmsgtag = msgtag;
- parm->ipflags1 = (IPNORPY | IPBUFLST | flags1);
- b2f0_result = b2f0(SEND, parm);
-
- if ((!b2f0_result) && (msgid))
- *msgid = parm->ipmsgid;
- release_param(parm);
-
- iucv_debug(2, "exiting");
- return b2f0_result;
-}
-
-/*
- * Name: iucv_send_prmmsg
- * Purpose: This function transmits data to another application.
- * Prmmsg specifies that the 8-bytes of data are to be moved
- * into the parameter list. This is a one-way message and the
- * receiver will not reply to the message.
- * Input: pathid - path identification number
- * trgcls - specifies target class
- * srccls - specifies the source message class
- * msgtag - specifies a tag to be associated with the message
- * flags1 - option for path
- * IPPRTY- specifies if you want to send priority message
- * prmmsg - 8-bytes of data to be placed into parameter list
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
-*/
-int
-iucv_send_prmmsg (__u16 pathid,
- __u32 * msgid,
- __u32 trgcls,
- __u32 srccls, __u32 msgtag, int flags1, __u8 prmmsg[8])
-{
- iparml_dpl *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- parm = (iparml_dpl *)grab_param();
-
- parm->ippathid = pathid;
- parm->iptrgcls = trgcls;
- parm->ipsrccls = srccls;
- parm->ipmsgtag = msgtag;
- parm->ipflags1 = (IPRMDATA | IPNORPY | flags1);
- memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
-
- b2f0_result = b2f0(SEND, parm);
-
- if ((!b2f0_result) && (msgid))
- *msgid = parm->ipmsgid;
- release_param(parm);
-
- iucv_debug(2, "exiting");
-
- return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way
- * Purpose: This function transmits data to another application.
- * Data to be transmitted is in a buffer. The receiver
- * of the send is expected to reply to the message and
- * a buffer is provided into which IUCV moves the reply
- * to this message.
- * Input: pathid - path identification number
- * trgcls - specifies target class
- * srccls - specifies the source message class
- * msgtag - specifies a tag associated with the message
- * flags1 - option for path
- * IPPRTY- specifies if you want to send priority message
- * buffer - address of send buffer
- * buflen - length of send buffer
- * ansbuf - address of buffer to reply with
- * anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- * (-EINVAL) - buffer or ansbuf address is NULL
- */
-int
-iucv_send2way (__u16 pathid,
- __u32 * msgid,
- __u32 trgcls,
- __u32 srccls,
- __u32 msgtag,
- int flags1,
- void *buffer, ulong buflen, void *ansbuf, ulong anslen)
-{
- iparml_db *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- if (!buffer || !ansbuf)
- return -EINVAL;
-
- parm = (iparml_db *)grab_param();
-
- parm->ippathid = pathid;
- parm->iptrgcls = trgcls;
- parm->ipbfadr1 = (__u32) ((ulong) buffer);
- parm->ipbfln1f = (__u32) buflen; /* length of message */
- parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
- parm->ipbfln2f = (__u32) anslen;
- parm->ipsrccls = srccls;
- parm->ipmsgtag = msgtag;
- parm->ipflags1 = flags1; /* priority message */
-
- b2f0_result = b2f0(SEND, parm);
-
- if ((!b2f0_result) && (msgid))
- *msgid = parm->ipmsgid;
- release_param(parm);
-
- iucv_debug(2, "exiting");
-
- return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way_array
- * Purpose: This function transmits data to another application.
- * The contents of buffer is the address of the array of
- * addresses and lengths of discontiguous buffers that hold
- * the message text. The receiver of the send is expected to
- * reply to the message and a buffer is provided into which
- * IUCV moves the reply to this message.
- * Input: pathid - path identification number
- * trgcls - specifies target class
- * srccls - specifies the source message class
- * msgtag - spcifies a tag to be associated with the message
- * flags1 - option for path
- * IPPRTY- specifies if you want to send priority message
- * buffer - address of array of send buffers
- * buflen - total length of send buffers
- * ansbuf - address of buffer to reply with
- * anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- * (-EINVAL) - buffer address is NULL
- */
-int
-iucv_send2way_array (__u16 pathid,
- __u32 * msgid,
- __u32 trgcls,
- __u32 srccls,
- __u32 msgtag,
- int flags1,
- iucv_array_t * buffer,
- ulong buflen, iucv_array_t * ansbuf, ulong anslen)
-{
- iparml_db *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- if (!buffer || !ansbuf)
- return -EINVAL;
-
- parm = (iparml_db *)grab_param();
-
- parm->ippathid = pathid;
- parm->iptrgcls = trgcls;
- parm->ipbfadr1 = (__u32) ((ulong) buffer);
- parm->ipbfln1f = (__u32) buflen; /* length of message */
- parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
- parm->ipbfln2f = (__u32) anslen;
- parm->ipsrccls = srccls;
- parm->ipmsgtag = msgtag;
- parm->ipflags1 = (IPBUFLST | IPANSLST | flags1);
- b2f0_result = b2f0(SEND, parm);
- if ((!b2f0_result) && (msgid))
- *msgid = parm->ipmsgid;
- release_param(parm);
-
- iucv_debug(2, "exiting");
- return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way_prmmsg
- * Purpose: This function transmits data to another application.
- * Prmmsg specifies that the 8-bytes of data are to be moved
- * into the parameter list. This is a two-way message and the
- * receiver of the message is expected to reply. A buffer
- * is provided into which IUCV moves the reply to this
- * message.
- * Input: pathid - path identification number
- * trgcls - specifies target class
- * srccls - specifies the source message class
- * msgtag - specifies a tag to be associated with the message
- * flags1 - option for path
- * IPPRTY- specifies if you want to send priority message
- * prmmsg - 8-bytes of data to be placed in parameter list
- * ansbuf - address of buffer to reply with
- * anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- * (-EINVAL) - buffer address is NULL
-*/
-int
-iucv_send2way_prmmsg (__u16 pathid,
- __u32 * msgid,
- __u32 trgcls,
- __u32 srccls,
- __u32 msgtag,
- ulong flags1, __u8 prmmsg[8], void *ansbuf, ulong anslen)
-{
- iparml_dpl *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- if (!ansbuf)
- return -EINVAL;
-
- parm = (iparml_dpl *)grab_param();
-
- parm->ippathid = pathid;
- parm->iptrgcls = trgcls;
- parm->ipsrccls = srccls;
- parm->ipmsgtag = msgtag;
- parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
- parm->ipbfln2f = (__u32) anslen;
- parm->ipflags1 = (IPRMDATA | flags1); /* message in prmlist */
- memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
-
- b2f0_result = b2f0(SEND, parm);
-
- if ((!b2f0_result) && (msgid))
- *msgid = parm->ipmsgid;
- release_param(parm);
-
- iucv_debug(2, "exiting");
-
- return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way_prmmsg_array
- * Purpose: This function transmits data to another application.
- * Prmmsg specifies that the 8-bytes of data are to be moved
- * into the parameter list. This is a two-way message and the
- * receiver of the message is expected to reply. A buffer
- * is provided into which IUCV moves the reply to this
- * message. The contents of ansbuf is the address of the
- * array of addresses and lengths of discontiguous buffers
- * that contain the reply.
- * Input: pathid - path identification number
- * trgcls - specifies target class
- * srccls - specifies the source message class
- * msgtag - specifies a tag to be associated with the message
- * flags1 - option for path
- * IPPRTY- specifies if you want to send priority message
- * prmmsg - 8-bytes of data to be placed into the parameter list
- * ansbuf - address of buffer to reply with
- * anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- * (-EINVAL) - ansbuf address is NULL
- */
-int
-iucv_send2way_prmmsg_array (__u16 pathid,
- __u32 * msgid,
- __u32 trgcls,
- __u32 srccls,
- __u32 msgtag,
- int flags1,
- __u8 prmmsg[8],
- iucv_array_t * ansbuf, ulong anslen)
-{
- iparml_dpl *parm;
- ulong b2f0_result;
-
- iucv_debug(2, "entering");
-
- if (!ansbuf)
- return -EINVAL;
-
- parm = (iparml_dpl *)grab_param();
-
- parm->ippathid = pathid;
- parm->iptrgcls = trgcls;
- parm->ipsrccls = srccls;
- parm->ipmsgtag = msgtag;
- parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
- parm->ipbfln2f = (__u32) anslen;
- parm->ipflags1 = (IPRMDATA | IPANSLST | flags1);
- memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
- b2f0_result = b2f0(SEND, parm);
- if ((!b2f0_result) && (msgid))
- *msgid = parm->ipmsgid;
- release_param(parm);
-
- iucv_debug(2, "exiting");
- return b2f0_result;
-}
-
-void
-iucv_setmask_cpuid (void *result)
-{
- iparml_set_mask *parm;
-
- iucv_debug(1, "entering");
- parm = (iparml_set_mask *)grab_param();
- parm->ipmask = *((__u8*)result);
- *((ulong *)result) = b2f0(SETMASK, parm);
- release_param(parm);
-
- iucv_debug(1, "b2f0_result = %ld", *((ulong *)result));
- iucv_debug(1, "exiting");
-}
-
-/*
- * Name: iucv_setmask
- * Purpose: This function enables or disables the following IUCV
- * external interruptions: Nonpriority and priority message
- * interrupts, nonpriority and priority reply interrupts.
- * Input: SetMaskFlag - options for interrupts
- * 0x80 - Nonpriority_MessagePendingInterruptsFlag
- * 0x40 - Priority_MessagePendingInterruptsFlag
- * 0x20 - Nonpriority_MessageCompletionInterruptsFlag
- * 0x10 - Priority_MessageCompletionInterruptsFlag
- * 0x08 - IUCVControlInterruptsFlag
- * Output: NA
- * Return: b2f0_result - return code from CP
-*/
-int
-iucv_setmask (int SetMaskFlag)
-{
- union {
- ulong result;
- __u8 param;
- } u;
- int cpu;
-
- u.param = SetMaskFlag;
- cpu = get_cpu();
- smp_call_function_on(iucv_setmask_cpuid, &u, 0, 1, iucv_cpuid);
- put_cpu();
-
- return u.result;
-}
-
-/**
- * iucv_sever:
- * @pathid: Path identification number
- * @user_data: 16-byte of user data
- *
- * This function terminates an iucv path.
- * Returns: return code from CP
- */
-int
-iucv_sever(__u16 pathid, __u8 user_data[16])
-{
- iparml_control *parm;
- ulong b2f0_result = 0;
-
- iucv_debug(1, "entering");
- parm = (iparml_control *)grab_param();
-
- memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
- parm->ippathid = pathid;
-
- b2f0_result = b2f0(SEVER, parm);
-
- if (!b2f0_result)
- iucv_remove_pathid(pathid);
- release_param(parm);
-
- iucv_debug(1, "exiting");
- return b2f0_result;
-}
-
-/*
- * Interrupt Handlers
- *******************************************************************************/
-
-/**
- * iucv_irq_handler:
- * @regs: Current registers
- * @code: irq code
- *
- * Handles external interrupts coming in from CP.
- * Places the interrupt buffer on a queue and schedules iucv_tasklet_handler().
- */
-static void
-iucv_irq_handler(__u16 code)
-{
- iucv_irqdata *irqdata;
-
- irqdata = kmalloc(sizeof(iucv_irqdata), GFP_ATOMIC);
- if (!irqdata) {
- printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
- return;
- }
-
- memcpy(&irqdata->data, iucv_external_int_buffer,
- sizeof(iucv_GeneralInterrupt));
-
- spin_lock(&iucv_irq_queue_lock);
- list_add_tail(&irqdata->queue, &iucv_irq_queue);
- spin_unlock(&iucv_irq_queue_lock);
-
- tasklet_schedule(&iucv_tasklet);
-}
-
-/**
- * iucv_do_int:
- * @int_buf: Pointer to copy of external interrupt buffer
- *
- * The workhorse for handling interrupts queued by iucv_irq_handler().
- * This function is called from the bottom half iucv_tasklet_handler().
- */
-static void
-iucv_do_int(iucv_GeneralInterrupt * int_buf)
-{
- handler *h = NULL;
- struct list_head *lh;
- ulong flags;
- iucv_interrupt_ops_t *interrupt = NULL; /* interrupt addresses */
- __u8 temp_buff1[24], temp_buff2[24]; /* masked handler id. */
- int rc = 0, j = 0;
- __u8 no_listener[16] = "NO LISTENER";
-
- iucv_debug(2, "entering, pathid %d, type %02X",
- int_buf->ippathid, int_buf->iptype);
- iucv_dumpit("External Interrupt Buffer:",
- int_buf, sizeof(iucv_GeneralInterrupt));
-
- ASCEBC (no_listener, 16);
-
- if (int_buf->iptype != 01) {
- if ((int_buf->ippathid) > (max_connections - 1)) {
- printk(KERN_WARNING "%s: Got interrupt with pathid %d"
- " > max_connections (%ld)\n", __FUNCTION__,
- int_buf->ippathid, max_connections - 1);
- } else {
- h = iucv_pathid_table[int_buf->ippathid];
- interrupt = h->interrupt_table;
- iucv_dumpit("Handler:", h, sizeof(handler));
- }
- }
-
- /* end of if statement */
- switch (int_buf->iptype) {
- case 0x01: /* connection pending */
- if (messagesDisabled) {
- iucv_setmask(~0);
- messagesDisabled = 0;
- }
- spin_lock_irqsave(&iucv_lock, flags);
- list_for_each(lh, &iucv_handler_table) {
- h = list_entry(lh, handler, list);
- memcpy(temp_buff1, &(int_buf->ipvmid), 24);
- memcpy(temp_buff2, &(h->id.userid), 24);
- for (j = 0; j < 24; j++) {
- temp_buff1[j] &= (h->id.mask)[j];
- temp_buff2[j] &= (h->id.mask)[j];
- }
-
- iucv_dumpit("temp_buff1:",
- temp_buff1, sizeof(temp_buff1));
- iucv_dumpit("temp_buff2",
- temp_buff2, sizeof(temp_buff2));
-
- if (!memcmp (temp_buff1, temp_buff2, 24)) {
-
- iucv_debug(2,
- "found a matching handler");
- break;
- } else
- h = NULL;
- }
- spin_unlock_irqrestore (&iucv_lock, flags);
- if (h) {
- /* ADD PATH TO PATHID TABLE */
- rc = iucv_add_pathid(int_buf->ippathid, h);
- if (rc) {
- iucv_sever (int_buf->ippathid,
- no_listener);
- iucv_debug(1,
- "add_pathid failed, rc = %d",
- rc);
- } else {
- interrupt = h->interrupt_table;
- if (interrupt->ConnectionPending) {
- EBCASC (int_buf->ipvmid, 8);
- interrupt->ConnectionPending(
- (iucv_ConnectionPending *)int_buf,
- h->pgm_data);
- } else
- iucv_sever(int_buf->ippathid,
- no_listener);
- }
- } else
- iucv_sever(int_buf->ippathid, no_listener);
- break;
-
- case 0x02: /*connection complete */
- if (messagesDisabled) {
- iucv_setmask(~0);
- messagesDisabled = 0;
- }
- if (h) {
- if (interrupt->ConnectionComplete)
- {
- interrupt->ConnectionComplete(
- (iucv_ConnectionComplete *)int_buf,
- h->pgm_data);
- }
- else
- iucv_debug(1,
- "ConnectionComplete not called");
- } else
- iucv_sever(int_buf->ippathid, no_listener);
- break;
-
- case 0x03: /* connection severed */
- if (messagesDisabled) {
- iucv_setmask(~0);
- messagesDisabled = 0;
- }
- if (h) {
- if (interrupt->ConnectionSevered)
- interrupt->ConnectionSevered(
- (iucv_ConnectionSevered *)int_buf,
- h->pgm_data);
-
- else
- iucv_sever (int_buf->ippathid, no_listener);
- } else
- iucv_sever(int_buf->ippathid, no_listener);
- break;
-
- case 0x04: /* connection quiesced */
- if (messagesDisabled) {
- iucv_setmask(~0);
- messagesDisabled = 0;
- }
- if (h) {
- if (interrupt->ConnectionQuiesced)
- interrupt->ConnectionQuiesced(
- (iucv_ConnectionQuiesced *)int_buf,
- h->pgm_data);
- else
- iucv_debug(1,
- "ConnectionQuiesced not called");
- }
- break;
-
- case 0x05: /* connection resumed */
- if (messagesDisabled) {
- iucv_setmask(~0);
- messagesDisabled = 0;
- }
- if (h) {
- if (interrupt->ConnectionResumed)
- interrupt->ConnectionResumed(
- (iucv_ConnectionResumed *)int_buf,
- h->pgm_data);
- else
- iucv_debug(1,
- "ConnectionResumed not called");
- }
- break;
-
- case 0x06: /* priority message complete */
- case 0x07: /* nonpriority message complete */
- if (h) {
- if (interrupt->MessageComplete)
- interrupt->MessageComplete(
- (iucv_MessageComplete *)int_buf,
- h->pgm_data);
- else
- iucv_debug(2,
- "MessageComplete not called");
- }
- break;
-
- case 0x08: /* priority message pending */
- case 0x09: /* nonpriority message pending */
- if (h) {
- if (interrupt->MessagePending)
- interrupt->MessagePending(
- (iucv_MessagePending *) int_buf,
- h->pgm_data);
- else
- iucv_debug(2,
- "MessagePending not called");
- }
- break;
- default: /* unknown iucv type */
- printk(KERN_WARNING "%s: unknown iucv interrupt\n",
- __FUNCTION__);
- break;
- } /* end switch */
-
- iucv_debug(2, "exiting pathid %d, type %02X",
- int_buf->ippathid, int_buf->iptype);
-
- return;
-}
-
-/**
- * iucv_tasklet_handler:
- *
- * This function loops over the queue of irq buffers and runs iucv_do_int()
- * on every queue element.
- */
-static void
-iucv_tasklet_handler(unsigned long ignored)
-{
- struct list_head head;
- struct list_head *next;
- ulong flags;
-
- spin_lock_irqsave(&iucv_irq_queue_lock, flags);
- list_add(&head, &iucv_irq_queue);
- list_del_init(&iucv_irq_queue);
- spin_unlock_irqrestore (&iucv_irq_queue_lock, flags);
-
- next = head.next;
- while (next != &head) {
- iucv_irqdata *p = list_entry(next, iucv_irqdata, queue);
-
- next = next->next;
- iucv_do_int(&p->data);
- kfree(p);
- }
-
- return;
-}
-
-subsys_initcall(iucv_init);
-module_exit(iucv_exit);
-
-/**
- * Export all public stuff
- */
-EXPORT_SYMBOL (iucv_bus);
-EXPORT_SYMBOL (iucv_root);
-EXPORT_SYMBOL (iucv_accept);
-EXPORT_SYMBOL (iucv_connect);
-#if 0
-EXPORT_SYMBOL (iucv_purge);
-EXPORT_SYMBOL (iucv_query_maxconn);
-EXPORT_SYMBOL (iucv_query_bufsize);
-EXPORT_SYMBOL (iucv_quiesce);
-#endif
-EXPORT_SYMBOL (iucv_receive);
-#if 0
-EXPORT_SYMBOL (iucv_receive_array);
-#endif
-EXPORT_SYMBOL (iucv_reject);
-#if 0
-EXPORT_SYMBOL (iucv_reply);
-EXPORT_SYMBOL (iucv_reply_array);
-EXPORT_SYMBOL (iucv_resume);
-#endif
-EXPORT_SYMBOL (iucv_reply_prmmsg);
-EXPORT_SYMBOL (iucv_send);
-EXPORT_SYMBOL (iucv_send2way);
-EXPORT_SYMBOL (iucv_send2way_array);
-EXPORT_SYMBOL (iucv_send2way_prmmsg);
-EXPORT_SYMBOL (iucv_send2way_prmmsg_array);
-#if 0
-EXPORT_SYMBOL (iucv_send_array);
-EXPORT_SYMBOL (iucv_send_prmmsg);
-EXPORT_SYMBOL (iucv_setmask);
-#endif
-EXPORT_SYMBOL (iucv_sever);
-EXPORT_SYMBOL (iucv_register_program);
-EXPORT_SYMBOL (iucv_unregister_program);
diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h
deleted file mode 100644
index 5b6b1b7241c9..000000000000
--- a/drivers/s390/net/iucv.h
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- * drivers/s390/net/iucv.h
- * IUCV base support.
- *
- * S390 version
- * Copyright (C) 2000 IBM Corporation
- * Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
- * Xenia Tkatschow (xenia@us.ibm.com)
- *
- *
- * Functionality:
- * To explore any of the IUCV functions, one must first register
- * their program using iucv_register_program(). Once your program has
- * successfully completed a register, it can exploit the other functions.
- * For furthur reference on all IUCV functionality, refer to the
- * CP Programming Services book, also available on the web
- * thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
- *
- * Definition of Return Codes
- * -All positive return codes including zero are reflected back
- * from CP except for iucv_register_program. The definition of each
- * return code can be found in CP Programming Services book.
- * Also available on the web thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
- * - Return Code of:
- * (-EINVAL) Invalid value
- * (-ENOMEM) storage allocation failed
- * pgmask defined in iucv_register_program will be set depending on input
- * paramters.
- *
- */
-
-#include <linux/types.h>
-#include <asm/debug.h>
-
-/**
- * Debug Facility stuff
- */
-#define IUCV_DBF_SETUP_NAME "iucv_setup"
-#define IUCV_DBF_SETUP_LEN 32
-#define IUCV_DBF_SETUP_PAGES 2
-#define IUCV_DBF_SETUP_NR_AREAS 1
-#define IUCV_DBF_SETUP_LEVEL 3
-
-#define IUCV_DBF_DATA_NAME "iucv_data"
-#define IUCV_DBF_DATA_LEN 128
-#define IUCV_DBF_DATA_PAGES 2
-#define IUCV_DBF_DATA_NR_AREAS 1
-#define IUCV_DBF_DATA_LEVEL 2
-
-#define IUCV_DBF_TRACE_NAME "iucv_trace"
-#define IUCV_DBF_TRACE_LEN 16
-#define IUCV_DBF_TRACE_PAGES 4
-#define IUCV_DBF_TRACE_NR_AREAS 1
-#define IUCV_DBF_TRACE_LEVEL 3
-
-#define IUCV_DBF_TEXT(name,level,text) \
- do { \
- debug_text_event(iucv_dbf_##name,level,text); \
- } while (0)
-
-#define IUCV_DBF_HEX(name,level,addr,len) \
- do { \
- debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
- } while (0)
-
-DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
-
-#define IUCV_DBF_TEXT_(name,level,text...) \
- do { \
- char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf); \
- sprintf(iucv_dbf_txt_buf, text); \
- debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \
- put_cpu_var(iucv_dbf_txt_buf); \
- } while (0)
-
-#define IUCV_DBF_SPRINTF(name,level,text...) \
- do { \
- debug_sprintf_event(iucv_dbf_trace, level, ##text ); \
- debug_sprintf_event(iucv_dbf_trace, level, text ); \
- } while (0)
-
-/**
- * some more debug stuff
- */
-#define IUCV_HEXDUMP16(importance,header,ptr) \
-PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
- "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
- *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
- *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
- *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
- *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
- *(((char*)ptr)+12),*(((char*)ptr)+13), \
- *(((char*)ptr)+14),*(((char*)ptr)+15)); \
-PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
- "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
- *(((char*)ptr)+16),*(((char*)ptr)+17), \
- *(((char*)ptr)+18),*(((char*)ptr)+19), \
- *(((char*)ptr)+20),*(((char*)ptr)+21), \
- *(((char*)ptr)+22),*(((char*)ptr)+23), \
- *(((char*)ptr)+24),*(((char*)ptr)+25), \
- *(((char*)ptr)+26),*(((char*)ptr)+27), \
- *(((char*)ptr)+28),*(((char*)ptr)+29), \
- *(((char*)ptr)+30),*(((char*)ptr)+31));
-
-static inline void
-iucv_hex_dump(unsigned char *buf, size_t len)
-{
- size_t i;
-
- for (i = 0; i < len; i++) {
- if (i && !(i % 16))
- printk("\n");
- printk("%02x ", *(buf + i));
- }
- printk("\n");
-}
-/**
- * end of debug stuff
- */
-
-#define uchar unsigned char
-#define ushort unsigned short
-#define ulong unsigned long
-#define iucv_handle_t void *
-
-/* flags1:
- * All flags are defined in the field IPFLAGS1 of each function
- * and can be found in CP Programming Services.
- * IPLOCAL - Indicates the connect can only be satisfied on the
- * local system
- * IPPRTY - Indicates a priority message
- * IPQUSCE - Indicates you do not want to receive messages on a
- * path until an iucv_resume is issued
- * IPRMDATA - Indicates that the message is in the parameter list
- */
-#define IPLOCAL 0x01
-#define IPPRTY 0x20
-#define IPQUSCE 0x40
-#define IPRMDATA 0x80
-
-/* flags1_out:
- * All flags are defined in the output field of IPFLAGS1 for each function
- * and can be found in CP Programming Services.
- * IPNORPY - Specifies this is a one-way message and no reply is expected.
- * IPPRTY - Indicates a priority message is permitted. Defined in flags1.
- */
-#define IPNORPY 0x10
-
-#define Nonpriority_MessagePendingInterruptsFlag 0x80
-#define Priority_MessagePendingInterruptsFlag 0x40
-#define Nonpriority_MessageCompletionInterruptsFlag 0x20
-#define Priority_MessageCompletionInterruptsFlag 0x10
-#define IUCVControlInterruptsFlag 0x08
-#define AllInterrupts 0xf8
-/*
- * Mapping of external interrupt buffers should be used with the corresponding
- * interrupt types.
- * Names: iucv_ConnectionPending -> connection pending
- * iucv_ConnectionComplete -> connection complete
- * iucv_ConnectionSevered -> connection severed
- * iucv_ConnectionQuiesced -> connection quiesced
- * iucv_ConnectionResumed -> connection resumed
- * iucv_MessagePending -> message pending
- * iucv_MessageComplete -> message complete
- */
-typedef struct {
- u16 ippathid;
- uchar ipflags1;
- uchar iptype;
- u16 ipmsglim;
- u16 res1;
- uchar ipvmid[8];
- uchar ipuser[16];
- u32 res3;
- uchar ippollfg;
- uchar res4[3];
-} iucv_ConnectionPending;
-
-typedef struct {
- u16 ippathid;
- uchar ipflags1;
- uchar iptype;
- u16 ipmsglim;
- u16 res1;
- uchar res2[8];
- uchar ipuser[16];
- u32 res3;
- uchar ippollfg;
- uchar res4[3];
-} iucv_ConnectionComplete;
-
-typedef struct {
- u16 ippathid;
- uchar res1;
- uchar iptype;
- u32 res2;
- uchar res3[8];
- uchar ipuser[16];
- u32 res4;
- uchar ippollfg;
- uchar res5[3];
-} iucv_ConnectionSevered;
-
-typedef struct {
- u16 ippathid;
- uchar res1;
- uchar iptype;
- u32 res2;
- uchar res3[8];
- uchar ipuser[16];
- u32 res4;
- uchar ippollfg;
- uchar res5[3];
-} iucv_ConnectionQuiesced;
-
-typedef struct {
- u16 ippathid;
- uchar res1;
- uchar iptype;
- u32 res2;
- uchar res3[8];
- uchar ipuser[16];
- u32 res4;
- uchar ippollfg;
- uchar res5[3];
-} iucv_ConnectionResumed;
-
-typedef struct {
- u16 ippathid;
- uchar ipflags1;
- uchar iptype;
- u32 ipmsgid;
- u32 iptrgcls;
- union u2 {
- u32 iprmmsg1_u32;
- uchar iprmmsg1[4];
- } ln1msg1;
- union u1 {
- u32 ipbfln1f;
- uchar iprmmsg2[4];
- } ln1msg2;
- u32 res1[3];
- u32 ipbfln2f;
- uchar ippollfg;
- uchar res2[3];
-} iucv_MessagePending;
-
-typedef struct {
- u16 ippathid;
- uchar ipflags1;
- uchar iptype;
- u32 ipmsgid;
- u32 ipaudit;
- uchar iprmmsg[8];
- u32 ipsrccls;
- u32 ipmsgtag;
- u32 res;
- u32 ipbfln2f;
- uchar ippollfg;
- uchar res2[3];
-} iucv_MessageComplete;
-
-/*
- * iucv_interrupt_ops_t: Is a vector of functions that handle
- * IUCV interrupts.
- * Parameter list:
- * eib - is a pointer to a 40-byte area described
- * with one of the structures above.
- * pgm_data - this data is strictly for the
- * interrupt handler that is passed by
- * the application. This may be an address
- * or token.
-*/
-typedef struct {
- void (*ConnectionPending) (iucv_ConnectionPending * eib,
- void *pgm_data);
- void (*ConnectionComplete) (iucv_ConnectionComplete * eib,
- void *pgm_data);
- void (*ConnectionSevered) (iucv_ConnectionSevered * eib,
- void *pgm_data);
- void (*ConnectionQuiesced) (iucv_ConnectionQuiesced * eib,
- void *pgm_data);
- void (*ConnectionResumed) (iucv_ConnectionResumed * eib,
- void *pgm_data);
- void (*MessagePending) (iucv_MessagePending * eib, void *pgm_data);
- void (*MessageComplete) (iucv_MessageComplete * eib, void *pgm_data);
-} iucv_interrupt_ops_t;
-
-/*
- *iucv_array_t : Defines buffer array.
- * Inside the array may be 31- bit addresses and 31-bit lengths.
-*/
-typedef struct {
- u32 address;
- u32 length;
-} iucv_array_t __attribute__ ((aligned (8)));
-
-extern struct bus_type iucv_bus;
-extern struct device *iucv_root;
-
-/* -prototypes- */
-/*
- * Name: iucv_register_program
- * Purpose: Registers an application with IUCV
- * Input: prmname - user identification
- * userid - machine identification
- * pgmmask - indicates which bits in the prmname and userid combined will be
- * used to determine who is given control
- * ops - address of vector of interrupt handlers
- * pgm_data- application data passed to interrupt handlers
- * Output: NA
- * Return: address of handler
- * (0) - Error occurred, registration not completed.
- * NOTE: Exact cause of failure will be recorded in syslog.
-*/
-iucv_handle_t iucv_register_program (uchar pgmname[16],
- uchar userid[8],
- uchar pgmmask[24],
- iucv_interrupt_ops_t * ops,
- void *pgm_data);
-
-/*
- * Name: iucv_unregister_program
- * Purpose: Unregister application with IUCV
- * Input: address of handler
- * Output: NA
- * Return: (0) - Normal return
- * (-EINVAL) - Internal error, wild pointer
-*/
-int iucv_unregister_program (iucv_handle_t handle);
-
-/*
- * Name: iucv_accept
- * Purpose: This function is issued after the user receives a Connection Pending external
- * interrupt and now wishes to complete the IUCV communication path.
- * Input: pathid - u16 , Path identification number
- * msglim_reqstd - u16, The number of outstanding messages requested.
- * user_data - uchar[16], Data specified by the iucv_connect function.
- * flags1 - int, Contains options for this path.
- * -IPPRTY - 0x20- Specifies if you want to send priority message.
- * -IPRMDATA - 0x80, Specifies whether your program can handle a message
- * in the parameter list.
- * -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
- * established.
- * handle - iucv_handle_t, Address of handler.
- * pgm_data - void *, Application data passed to interrupt handlers.
- * flags1_out - int * Contains information about the path
- * - IPPRTY - 0x20, Indicates you may send priority messages.
- * msglim - *u16, Number of outstanding messages.
- * Output: return code from CP IUCV call.
-*/
-
-int iucv_accept (u16 pathid,
- u16 msglim_reqstd,
- uchar user_data[16],
- int flags1,
- iucv_handle_t handle,
- void *pgm_data, int *flags1_out, u16 * msglim);
-
-/*
- * Name: iucv_connect
- * Purpose: This function establishes an IUCV path. Although the connect may complete
- * successfully, you are not able to use the path until you receive an IUCV
- * Connection Complete external interrupt.
- * Input: pathid - u16 *, Path identification number
- * msglim_reqstd - u16, Number of outstanding messages requested
- * user_data - uchar[16], 16-byte user data
- * userid - uchar[8], User identification
- * system_name - uchar[8], 8-byte identifying the system name
- * flags1 - int, Contains options for this path.
- * -IPPRTY - 0x20, Specifies if you want to send priority message.
- * -IPRMDATA - 0x80, Specifies whether your program can handle a message
- * in the parameter list.
- * -IPQUSCE - 0x40, Specifies whether you want to quiesce the path being
- * established.
- * -IPLOCAL - 0X01, Allows an application to force the partner to be on
- * the local system. If local is specified then target class cannot be
- * specified.
- * flags1_out - int * Contains information about the path
- * - IPPRTY - 0x20, Indicates you may send priority messages.
- * msglim - * u16, Number of outstanding messages
- * handle - iucv_handle_t, Address of handler
- * pgm_data - void *, Application data passed to interrupt handlers
- * Output: return code from CP IUCV call
- * rc - return code from iucv_declare_buffer
- * -EINVAL - Invalid handle passed by application
- * -EINVAL - Pathid address is NULL
- * add_pathid_result - Return code from internal function add_pathid
-*/
-int
- iucv_connect (u16 * pathid,
- u16 msglim_reqstd,
- uchar user_data[16],
- uchar userid[8],
- uchar system_name[8],
- int flags1,
- int *flags1_out,
- u16 * msglim, iucv_handle_t handle, void *pgm_data);
-
-/*
- * Name: iucv_purge
- * Purpose: This function cancels a message that you have sent.
- * Input: pathid - Path identification number.
- * msgid - Specifies the message ID of the message to be purged.
- * srccls - Specifies the source message class.
- * Output: audit - Contains information about asynchronous error
- * that may have affected the normal completion
- * of this message.
- * Return: Return code from CP IUCV call.
-*/
-int iucv_purge (u16 pathid, u32 msgid, u32 srccls, __u32 *audit);
-/*
- * Name: iucv_query_maxconn
- * Purpose: This function determines the maximum number of communication paths you
- * may establish.
- * Return: maxconn - ulong, Maximum number of connection the virtual machine may
- * establish.
-*/
-ulong iucv_query_maxconn (void);
-
-/*
- * Name: iucv_query_bufsize
- * Purpose: This function determines how large an external interrupt
- * buffer IUCV requires to store information.
- * Return: bufsize - ulong, Size of external interrupt buffer.
- */
-ulong iucv_query_bufsize (void);
-
-/*
- * Name: iucv_quiesce
- * Purpose: This function temporarily suspends incoming messages on an
- * IUCV path. You can later reactivate the path by invoking
- * the iucv_resume function.
- * Input: pathid - Path identification number
- * user_data - 16-bytes of user data
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_quiesce (u16 pathid, uchar user_data[16]);
-
-/*
- * Name: iucv_receive
- * Purpose: This function receives messages that are being sent to you
- * over established paths. Data will be returned in buffer for length of
- * buflen.
- * Input:
- * pathid - Path identification number.
- * buffer - Address of buffer to receive.
- * buflen - Length of buffer to receive.
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
- * Output:
- * flags1_out: int *, Contains information about this path.
- * IPNORPY - 0x10 Specifies this is a one-way message and no reply is
- * expected.
- * IPPRTY - 0x20 Specifies if you want to send priority message.
- * IPRMDATA - 0x80 specifies the data is contained in the parameter list
- * residual_buffer - address of buffer updated by the number
- * of bytes you have received.
- * residual_length -
- * Contains one of the following values, if the receive buffer is:
- * The same length as the message, this field is zero.
- * Longer than the message, this field contains the number of
- * bytes remaining in the buffer.
- * Shorter than the message, this field contains the residual
- * count (that is, the number of bytes remaining in the
- * message that does not fit into the buffer. In this
- * case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - buffer address is pointing to NULL
-*/
-int iucv_receive (u16 pathid,
- u32 msgid,
- u32 trgcls,
- void *buffer,
- ulong buflen,
- int *flags1_out,
- ulong * residual_buffer, ulong * residual_length);
-
- /*
- * Name: iucv_receive_array
- * Purpose: This function receives messages that are being sent to you
- * over established paths. Data will be returned in first buffer for
- * length of first buffer.
- * Input: pathid - Path identification number.
- * msgid - specifies the message ID.
- * trgcls - Specifies target class.
- * buffer - Address of array of buffers.
- * buflen - Total length of buffers.
- * Output:
- * flags1_out: int *, Contains information about this path.
- * IPNORPY - 0x10 Specifies this is a one-way message and no reply is
- * expected.
- * IPPRTY - 0x20 Specifies if you want to send priority message.
- * IPRMDATA - 0x80 specifies the data is contained in the parameter list
- * residual_buffer - address points to the current list entry IUCV
- * is working on.
- * residual_length -
- * Contains one of the following values, if the receive buffer is:
- * The same length as the message, this field is zero.
- * Longer than the message, this field contains the number of
- * bytes remaining in the buffer.
- * Shorter than the message, this field contains the residual
- * count (that is, the number of bytes remaining in the
- * message that does not fit into the buffer. In this
- * case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
- */
-int iucv_receive_array (u16 pathid,
- u32 msgid,
- u32 trgcls,
- iucv_array_t * buffer,
- ulong buflen,
- int *flags1_out,
- ulong * residual_buffer, ulong * residual_length);
-
-/*
- * Name: iucv_reject
- * Purpose: The reject function refuses a specified message. Between the
- * time you are notified of a message and the time that you
- * complete the message, the message may be rejected.
- * Input: pathid - Path identification number.
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_reject (u16 pathid, u32 msgid, u32 trgcls);
-
-/*
- * Name: iucv_reply
- * Purpose: This function responds to the two-way messages that you
- * receive. You must identify completely the message to
- * which you wish to reply. ie, pathid, msgid, and trgcls.
- * Input: pathid - Path identification number.
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
- * flags1 - Option for path.
- * IPPRTY- 0x20, Specifies if you want to send priority message.
- * buffer - Address of reply buffer.
- * buflen - Length of reply buffer.
- * Output: residual_buffer - Address of buffer updated by the number
- * of bytes you have moved.
- * residual_length - Contains one of the following values:
- * If the answer buffer is the same length as the reply, this field
- * contains zero.
- * If the answer buffer is longer than the reply, this field contains
- * the number of bytes remaining in the buffer.
- * If the answer buffer is shorter than the reply, this field contains
- * a residual count (that is, the number of bytes remianing in the
- * reply that does not fit into the buffer. In this
- * case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_reply (u16 pathid,
- u32 msgid,
- u32 trgcls,
- int flags1,
- void *buffer, ulong buflen, ulong * residual_buffer,
- ulong * residual_length);
-
-/*
- * Name: iucv_reply_array
- * Purpose: This function responds to the two-way messages that you
- * receive. You must identify completely the message to
- * which you wish to reply. ie, pathid, msgid, and trgcls.
- * The array identifies a list of addresses and lengths of
- * discontiguous buffers that contains the reply data.
- * Input: pathid - Path identification number
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
- * flags1 - Option for path.
- * IPPRTY- 0x20, Specifies if you want to send priority message.
- * buffer - Address of array of reply buffers.
- * buflen - Total length of reply buffers.
- * Output: residual_buffer - Address of buffer which IUCV is currently working on.
- * residual_length - Contains one of the following values:
- * If the answer buffer is the same length as the reply, this field
- * contains zero.
- * If the answer buffer is longer than the reply, this field contains
- * the number of bytes remaining in the buffer.
- * If the answer buffer is shorter than the reply, this field contains
- * a residual count (that is, the number of bytes remianing in the
- * reply that does not fit into the buffer. In this
- * case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_reply_array (u16 pathid,
- u32 msgid,
- u32 trgcls,
- int flags1,
- iucv_array_t * buffer,
- ulong buflen, ulong * residual_address,
- ulong * residual_length);
-
-/*
- * Name: iucv_reply_prmmsg
- * Purpose: This function responds to the two-way messages that you
- * receive. You must identify completely the message to
- * which you wish to reply. ie, pathid, msgid, and trgcls.
- * Prmmsg signifies the data is moved into the
- * parameter list.
- * Input: pathid - Path identification number.
- * msgid - Specifies the message ID.
- * trgcls - Specifies target class.
- * flags1 - Option for path.
- * IPPRTY- 0x20 Specifies if you want to send priority message.
- * prmmsg - 8-bytes of data to be placed into the parameter.
- * list.
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_reply_prmmsg (u16 pathid,
- u32 msgid, u32 trgcls, int flags1, uchar prmmsg[8]);
-
-/*
- * Name: iucv_resume
- * Purpose: This function restores communications over a quiesced path
- * Input: pathid - Path identification number.
- * user_data - 16-bytes of user data.
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_resume (u16 pathid, uchar user_data[16]);
-
-/*
- * Name: iucv_send
- * Purpose: This function transmits data to another application.
- * Data to be transmitted is in a buffer and this is a
- * one-way message and the receiver will not reply to the
- * message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
- * flags1 - Option for path.
- * IPPRTY- 0x20 Specifies if you want to send priority message.
- * buffer - Address of send buffer.
- * buflen - Length of send buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send (u16 pathid,
- u32 * msgid,
- u32 trgcls,
- u32 srccls, u32 msgtag, int flags1, void *buffer, ulong buflen);
-
-/*
- * Name: iucv_send_array
- * Purpose: This function transmits data to another application.
- * The contents of buffer is the address of the array of
- * addresses and lengths of discontiguous buffers that hold
- * the message text. This is a one-way message and the
- * receiver will not reply to the message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated witht the message.
- * flags1 - Option for path.
- * IPPRTY- specifies if you want to send priority message.
- * buffer - Address of array of send buffers.
- * buflen - Total length of send buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send_array (u16 pathid,
- u32 * msgid,
- u32 trgcls,
- u32 srccls,
- u32 msgtag,
- int flags1, iucv_array_t * buffer, ulong buflen);
-
-/*
- * Name: iucv_send_prmmsg
- * Purpose: This function transmits data to another application.
- * Prmmsg specifies that the 8-bytes of data are to be moved
- * into the parameter list. This is a one-way message and the
- * receiver will not reply to the message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
- * flags1 - Option for path.
- * IPPRTY- 0x20 specifies if you want to send priority message.
- * prmmsg - 8-bytes of data to be placed into parameter list.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
-*/
-int iucv_send_prmmsg (u16 pathid,
- u32 * msgid,
- u32 trgcls,
- u32 srccls, u32 msgtag, int flags1, uchar prmmsg[8]);
-
-/*
- * Name: iucv_send2way
- * Purpose: This function transmits data to another application.
- * Data to be transmitted is in a buffer. The receiver
- * of the send is expected to reply to the message and
- * a buffer is provided into which IUCV moves the reply
- * to this message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag associated with the message.
- * flags1 - Option for path.
- * IPPRTY- 0x20 Specifies if you want to send priority message.
- * buffer - Address of send buffer.
- * buflen - Length of send buffer.
- * ansbuf - Address of buffer into which IUCV moves the reply of
- * this message.
- * anslen - Address of length of buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer or ansbuf address is NULL.
-*/
-int iucv_send2way (u16 pathid,
- u32 * msgid,
- u32 trgcls,
- u32 srccls,
- u32 msgtag,
- int flags1,
- void *buffer, ulong buflen, void *ansbuf, ulong anslen);
-
-/*
- * Name: iucv_send2way_array
- * Purpose: This function transmits data to another application.
- * The contents of buffer is the address of the array of
- * addresses and lengths of discontiguous buffers that hold
- * the message text. The receiver of the send is expected to
- * reply to the message and a buffer is provided into which
- * IUCV moves the reply to this message.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
- * flags1 - Option for path.
- * IPPRTY- 0x20 Specifies if you want to send priority message.
- * buffer - Sddress of array of send buffers.
- * buflen - Total length of send buffers.
- * ansbuf - Address of array of buffer into which IUCV moves the reply
- * of this message.
- * anslen - Address of length reply buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send2way_array (u16 pathid,
- u32 * msgid,
- u32 trgcls,
- u32 srccls,
- u32 msgtag,
- int flags1,
- iucv_array_t * buffer,
- ulong buflen, iucv_array_t * ansbuf, ulong anslen);
-
-/*
- * Name: iucv_send2way_prmmsg
- * Purpose: This function transmits data to another application.
- * Prmmsg specifies that the 8-bytes of data are to be moved
- * into the parameter list. This is a two-way message and the
- * receiver of the message is expected to reply. A buffer
- * is provided into which IUCV moves the reply to this
- * message.
- * Input: pathid - Rath identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
- * flags1 - Option for path.
- * IPPRTY- 0x20 Specifies if you want to send priority message.
- * prmmsg - 8-bytes of data to be placed in parameter list.
- * ansbuf - Address of buffer into which IUCV moves the reply of
- * this message.
- * anslen - Address of length of buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send2way_prmmsg (u16 pathid,
- u32 * msgid,
- u32 trgcls,
- u32 srccls,
- u32 msgtag,
- ulong flags1,
- uchar prmmsg[8], void *ansbuf, ulong anslen);
-
-/*
- * Name: iucv_send2way_prmmsg_array
- * Purpose: This function transmits data to another application.
- * Prmmsg specifies that the 8-bytes of data are to be moved
- * into the parameter list. This is a two-way message and the
- * receiver of the message is expected to reply. A buffer
- * is provided into which IUCV moves the reply to this
- * message. The contents of ansbuf is the address of the
- * array of addresses and lengths of discontiguous buffers
- * that contain the reply.
- * Input: pathid - Path identification number.
- * trgcls - Specifies target class.
- * srccls - Specifies the source message class.
- * msgtag - Specifies a tag to be associated with the message.
- * flags1 - Option for path.
- * IPPRTY- 0x20 specifies if you want to send priority message.
- * prmmsg - 8-bytes of data to be placed into the parameter list.
- * ansbuf - Address of array of buffer into which IUCV moves the reply
- * of this message.
- * anslen - Address of length of reply buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Ansbuf address is NULL.
-*/
-int iucv_send2way_prmmsg_array (u16 pathid,
- u32 * msgid,
- u32 trgcls,
- u32 srccls,
- u32 msgtag,
- int flags1,
- uchar prmmsg[8],
- iucv_array_t * ansbuf, ulong anslen);
-
-/*
- * Name: iucv_setmask
- * Purpose: This function enables or disables the following IUCV
- * external interruptions: Nonpriority and priority message
- * interrupts, nonpriority and priority reply interrupts.
- * Input: SetMaskFlag - options for interrupts
- * 0x80 - Nonpriority_MessagePendingInterruptsFlag
- * 0x40 - Priority_MessagePendingInterruptsFlag
- * 0x20 - Nonpriority_MessageCompletionInterruptsFlag
- * 0x10 - Priority_MessageCompletionInterruptsFlag
- * 0x08 - IUCVControlInterruptsFlag
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_setmask (int SetMaskFlag);
-
-/*
- * Name: iucv_sever
- * Purpose: This function terminates an IUCV path.
- * Input: pathid - Path identification number.
- * user_data - 16-bytes of user data.
- * Output: NA
- * Return: Return code from CP IUCV call.
- * (-EINVAL) - Interal error, wild pointer.
-*/
-int iucv_sever (u16 pathid, uchar user_data[16]);
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 3346088f47e0..6387b483f2bf 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,7 +1,7 @@
/*
* IUCV network driver
*
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
*
* Sysfs integration and all bugs therein by Cornelia Huck
@@ -58,13 +58,94 @@
#include <asm/io.h>
#include <asm/uaccess.h>
-#include "iucv.h"
+#include <net/iucv/iucv.h>
#include "fsm.h"
MODULE_AUTHOR
("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
+/**
+ * Debug Facility stuff
+ */
+#define IUCV_DBF_SETUP_NAME "iucv_setup"
+#define IUCV_DBF_SETUP_LEN 32
+#define IUCV_DBF_SETUP_PAGES 2
+#define IUCV_DBF_SETUP_NR_AREAS 1
+#define IUCV_DBF_SETUP_LEVEL 3
+
+#define IUCV_DBF_DATA_NAME "iucv_data"
+#define IUCV_DBF_DATA_LEN 128
+#define IUCV_DBF_DATA_PAGES 2
+#define IUCV_DBF_DATA_NR_AREAS 1
+#define IUCV_DBF_DATA_LEVEL 2
+
+#define IUCV_DBF_TRACE_NAME "iucv_trace"
+#define IUCV_DBF_TRACE_LEN 16
+#define IUCV_DBF_TRACE_PAGES 4
+#define IUCV_DBF_TRACE_NR_AREAS 1
+#define IUCV_DBF_TRACE_LEVEL 3
+
+#define IUCV_DBF_TEXT(name,level,text) \
+ do { \
+ debug_text_event(iucv_dbf_##name,level,text); \
+ } while (0)
+
+#define IUCV_DBF_HEX(name,level,addr,len) \
+ do { \
+ debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
+ } while (0)
+
+DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
+
+#define IUCV_DBF_TEXT_(name,level,text...) \
+ do { \
+ char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf); \
+ sprintf(iucv_dbf_txt_buf, text); \
+ debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \
+ put_cpu_var(iucv_dbf_txt_buf); \
+ } while (0)
+
+#define IUCV_DBF_SPRINTF(name,level,text...) \
+ do { \
+ debug_sprintf_event(iucv_dbf_trace, level, ##text ); \
+ debug_sprintf_event(iucv_dbf_trace, level, text ); \
+ } while (0)
+
+/**
+ * some more debug stuff
+ */
+#define IUCV_HEXDUMP16(importance,header,ptr) \
+PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
+ *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
+ *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
+ *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
+ *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
+ *(((char*)ptr)+12),*(((char*)ptr)+13), \
+ *(((char*)ptr)+14),*(((char*)ptr)+15)); \
+PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n", \
+ *(((char*)ptr)+16),*(((char*)ptr)+17), \
+ *(((char*)ptr)+18),*(((char*)ptr)+19), \
+ *(((char*)ptr)+20),*(((char*)ptr)+21), \
+ *(((char*)ptr)+22),*(((char*)ptr)+23), \
+ *(((char*)ptr)+24),*(((char*)ptr)+25), \
+ *(((char*)ptr)+26),*(((char*)ptr)+27), \
+ *(((char*)ptr)+28),*(((char*)ptr)+29), \
+ *(((char*)ptr)+30),*(((char*)ptr)+31));
+
+static inline void iucv_hex_dump(unsigned char *buf, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (i && !(i % 16))
+ printk("\n");
+ printk("%02x ", *(buf + i));
+ }
+ printk("\n");
+}
#define PRINTK_HEADER " iucv: " /* for debugging */
@@ -73,6 +154,25 @@ static struct device_driver netiucv_driver = {
.bus = &iucv_bus,
};
+static int netiucv_callback_connreq(struct iucv_path *,
+ u8 ipvmid[8], u8 ipuser[16]);
+static void netiucv_callback_connack(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_connrej(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_connsusp(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_connres(struct iucv_path *, u8 ipuser[16]);
+static void netiucv_callback_rx(struct iucv_path *, struct iucv_message *);
+static void netiucv_callback_txdone(struct iucv_path *, struct iucv_message *);
+
+static struct iucv_handler netiucv_handler = {
+ .path_pending = netiucv_callback_connreq,
+ .path_complete = netiucv_callback_connack,
+ .path_severed = netiucv_callback_connrej,
+ .path_quiesced = netiucv_callback_connsusp,
+ .path_resumed = netiucv_callback_connres,
+ .message_pending = netiucv_callback_rx,
+ .message_complete = netiucv_callback_txdone
+};
+
/**
* Per connection profiling data
*/
@@ -92,9 +192,8 @@ struct connection_profile {
* Representation of one iucv connection
*/
struct iucv_connection {
- struct iucv_connection *next;
- iucv_handle_t handle;
- __u16 pathid;
+ struct list_head list;
+ struct iucv_path *path;
struct sk_buff *rx_buff;
struct sk_buff *tx_buff;
struct sk_buff_head collect_queue;
@@ -112,12 +211,9 @@ struct iucv_connection {
/**
* Linked list of all connection structs.
*/
-struct iucv_connection_struct {
- struct iucv_connection *iucv_connections;
- rwlock_t iucv_rwlock;
-};
-
-static struct iucv_connection_struct iucv_conns;
+static struct list_head iucv_connection_list =
+ LIST_HEAD_INIT(iucv_connection_list);
+static rwlock_t iucv_connection_rwlock = RW_LOCK_UNLOCKED;
/**
* Representation of event-data for the
@@ -142,11 +238,11 @@ struct netiucv_priv {
/**
* Link level header for a packet.
*/
-typedef struct ll_header_t {
- __u16 next;
-} ll_header;
+struct ll_header {
+ u16 next;
+};
-#define NETIUCV_HDRLEN (sizeof(ll_header))
+#define NETIUCV_HDRLEN (sizeof(struct ll_header))
#define NETIUCV_BUFSIZE_MAX 32768
#define NETIUCV_BUFSIZE_DEFAULT NETIUCV_BUFSIZE_MAX
#define NETIUCV_MTU_MAX (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN)
@@ -158,36 +254,26 @@ typedef struct ll_header_t {
* Compatibility macros for busy handling
* of network devices.
*/
-static __inline__ void netiucv_clear_busy(struct net_device *dev)
+static inline void netiucv_clear_busy(struct net_device *dev)
{
- clear_bit(0, &(((struct netiucv_priv *)dev->priv)->tbusy));
+ struct netiucv_priv *priv = netdev_priv(dev);
+ clear_bit(0, &priv->tbusy);
netif_wake_queue(dev);
}
-static __inline__ int netiucv_test_and_set_busy(struct net_device *dev)
+static inline int netiucv_test_and_set_busy(struct net_device *dev)
{
+ struct netiucv_priv *priv = netdev_priv(dev);
netif_stop_queue(dev);
- return test_and_set_bit(0, &((struct netiucv_priv *)dev->priv)->tbusy);
+ return test_and_set_bit(0, &priv->tbusy);
}
-static __u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static __u8 iucvMagic[16] = {
+static u8 iucvMagic[16] = {
0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
};
/**
- * This mask means the 16-byte IUCV "magic" and the origin userid must
- * match exactly as specified in order to give connection_pending()
- * control.
- */
-static __u8 netiucv_mask[] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-/**
* Convert an iucv userId to its printable
* form (strip whitespace at end).
*
@@ -195,8 +281,7 @@ static __u8 netiucv_mask[] = {
*
* @returns The printable string (static data!!)
*/
-static __inline__ char *
-netiucv_printname(char *name)
+static inline char *netiucv_printname(char *name)
{
static char tmp[9];
char *p = tmp;
@@ -379,8 +464,7 @@ static debug_info_t *iucv_dbf_trace = NULL;
DEFINE_PER_CPU(char[256], iucv_dbf_txt_buf);
-static void
-iucv_unregister_dbf_views(void)
+static void iucv_unregister_dbf_views(void)
{
if (iucv_dbf_setup)
debug_unregister(iucv_dbf_setup);
@@ -389,8 +473,7 @@ iucv_unregister_dbf_views(void)
if (iucv_dbf_trace)
debug_unregister(iucv_dbf_trace);
}
-static int
-iucv_register_dbf_views(void)
+static int iucv_register_dbf_views(void)
{
iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME,
IUCV_DBF_SETUP_PAGES,
@@ -422,125 +505,111 @@ iucv_register_dbf_views(void)
return 0;
}
-/**
+/*
* Callback-wrappers, called from lowlevel iucv layer.
- *****************************************************************************/
+ */
-static void
-netiucv_callback_rx(iucv_MessagePending *eib, void *pgm_data)
+static void netiucv_callback_rx(struct iucv_path *path,
+ struct iucv_message *msg)
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
+ struct iucv_connection *conn = path->private;
struct iucv_event ev;
ev.conn = conn;
- ev.data = (void *)eib;
-
+ ev.data = msg;
fsm_event(conn->fsm, CONN_EVENT_RX, &ev);
}
-static void
-netiucv_callback_txdone(iucv_MessageComplete *eib, void *pgm_data)
+static void netiucv_callback_txdone(struct iucv_path *path,
+ struct iucv_message *msg)
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
+ struct iucv_connection *conn = path->private;
struct iucv_event ev;
ev.conn = conn;
- ev.data = (void *)eib;
+ ev.data = msg;
fsm_event(conn->fsm, CONN_EVENT_TXDONE, &ev);
}
-static void
-netiucv_callback_connack(iucv_ConnectionComplete *eib, void *pgm_data)
+static void netiucv_callback_connack(struct iucv_path *path, u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
- struct iucv_event ev;
+ struct iucv_connection *conn = path->private;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, &ev);
+ fsm_event(conn->fsm, CONN_EVENT_CONN_ACK, conn);
}
-static void
-netiucv_callback_connreq(iucv_ConnectionPending *eib, void *pgm_data)
+static int netiucv_callback_connreq(struct iucv_path *path,
+ u8 ipvmid[8], u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
+ struct iucv_connection *conn = path->private;
struct iucv_event ev;
+ int rc;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);
+ if (memcmp(iucvMagic, ipuser, sizeof(ipuser)))
+ /* ipuser must match iucvMagic. */
+ return -EINVAL;
+ rc = -EINVAL;
+ read_lock_bh(&iucv_connection_rwlock);
+ list_for_each_entry(conn, &iucv_connection_list, list) {
+ if (strncmp(ipvmid, conn->userid, 8))
+ continue;
+ /* Found a matching connection for this path. */
+ conn->path = path;
+ ev.conn = conn;
+ ev.data = path;
+ fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev);
+ rc = 0;
+ }
+ read_unlock_bh(&iucv_connection_rwlock);
+ return rc;
}
-static void
-netiucv_callback_connrej(iucv_ConnectionSevered *eib, void *pgm_data)
+static void netiucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
- struct iucv_event ev;
+ struct iucv_connection *conn = path->private;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, &ev);
+ fsm_event(conn->fsm, CONN_EVENT_CONN_REJ, conn);
}
-static void
-netiucv_callback_connsusp(iucv_ConnectionQuiesced *eib, void *pgm_data)
+static void netiucv_callback_connsusp(struct iucv_path *path, u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
- struct iucv_event ev;
+ struct iucv_connection *conn = path->private;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, &ev);
+ fsm_event(conn->fsm, CONN_EVENT_CONN_SUS, conn);
}
-static void
-netiucv_callback_connres(iucv_ConnectionResumed *eib, void *pgm_data)
+static void netiucv_callback_connres(struct iucv_path *path, u8 ipuser[16])
{
- struct iucv_connection *conn = (struct iucv_connection *)pgm_data;
- struct iucv_event ev;
+ struct iucv_connection *conn = path->private;
- ev.conn = conn;
- ev.data = (void *)eib;
- fsm_event(conn->fsm, CONN_EVENT_CONN_RES, &ev);
-}
-
-static iucv_interrupt_ops_t netiucv_ops = {
- .ConnectionPending = netiucv_callback_connreq,
- .ConnectionComplete = netiucv_callback_connack,
- .ConnectionSevered = netiucv_callback_connrej,
- .ConnectionQuiesced = netiucv_callback_connsusp,
- .ConnectionResumed = netiucv_callback_connres,
- .MessagePending = netiucv_callback_rx,
- .MessageComplete = netiucv_callback_txdone
-};
+ fsm_event(conn->fsm, CONN_EVENT_CONN_RES, conn);
+}
/**
* Dummy NOP action for all statemachines
*/
-static void
-fsm_action_nop(fsm_instance *fi, int event, void *arg)
+static void fsm_action_nop(fsm_instance *fi, int event, void *arg)
{
}
-/**
+/*
* Actions of the connection statemachine
- *****************************************************************************/
+ */
/**
- * Helper function for conn_action_rx()
- * Unpack a just received skb and hand it over to
- * upper layers.
+ * netiucv_unpack_skb
+ * @conn: The connection where this skb has been received.
+ * @pskb: The received skb.
*
- * @param conn The connection where this skb has been received.
- * @param pskb The received skb.
+ * Unpack a just received skb and hand it over to upper layers.
+ * Helper function for conn_action_rx.
*/
-//static __inline__ void
-static void
-netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
+static void netiucv_unpack_skb(struct iucv_connection *conn,
+ struct sk_buff *pskb)
{
struct net_device *dev = conn->netdev;
- struct netiucv_priv *privptr = dev->priv;
- __u16 offset = 0;
+ struct netiucv_priv *privptr = netdev_priv(dev);
+ u16 offset = 0;
skb_put(pskb, NETIUCV_HDRLEN);
pskb->dev = dev;
@@ -549,7 +618,7 @@ netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
while (1) {
struct sk_buff *skb;
- ll_header *header = (ll_header *)pskb->data;
+ struct ll_header *header = (struct ll_header *) pskb->data;
if (!header->next)
break;
@@ -595,40 +664,37 @@ netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
}
}
-static void
-conn_action_rx(fsm_instance *fi, int event, void *arg)
+static void conn_action_rx(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
+ struct iucv_event *ev = arg;
struct iucv_connection *conn = ev->conn;
- iucv_MessagePending *eib = (iucv_MessagePending *)ev->data;
- struct netiucv_priv *privptr =(struct netiucv_priv *)conn->netdev->priv;
-
- __u32 msglen = eib->ln1msg2.ipbfln1f;
+ struct iucv_message *msg = ev->data;
+ struct netiucv_priv *privptr = netdev_priv(conn->netdev);
int rc;
IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
if (!conn->netdev) {
- /* FRITZ: How to tell iucv LL to drop the msg? */
+ iucv_message_reject(conn->path, msg);
PRINT_WARN("Received data for unlinked connection\n");
IUCV_DBF_TEXT(data, 2,
- "Received data for unlinked connection\n");
+ "Received data for unlinked connection\n");
return;
}
- if (msglen > conn->max_buffsize) {
- /* FRITZ: How to tell iucv LL to drop the msg? */
+ if (msg->length > conn->max_buffsize) {
+ iucv_message_reject(conn->path, msg);
privptr->stats.rx_dropped++;
PRINT_WARN("msglen %d > max_buffsize %d\n",
- msglen, conn->max_buffsize);
+ msg->length, conn->max_buffsize);
IUCV_DBF_TEXT_(data, 2, "msglen %d > max_buffsize %d\n",
- msglen, conn->max_buffsize);
+ msg->length, conn->max_buffsize);
return;
}
conn->rx_buff->data = conn->rx_buff->tail = conn->rx_buff->head;
conn->rx_buff->len = 0;
- rc = iucv_receive(conn->pathid, eib->ipmsgid, eib->iptrgcls,
- conn->rx_buff->data, msglen, NULL, NULL, NULL);
- if (rc || msglen < 5) {
+ rc = iucv_message_receive(conn->path, msg, 0, conn->rx_buff->data,
+ msg->length, NULL);
+ if (rc || msg->length < 5) {
privptr->stats.rx_errors++;
PRINT_WARN("iucv_receive returned %08x\n", rc);
IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_receive\n", rc);
@@ -637,26 +703,26 @@ conn_action_rx(fsm_instance *fi, int event, void *arg)
netiucv_unpack_skb(conn, conn->rx_buff);
}
-static void
-conn_action_txdone(fsm_instance *fi, int event, void *arg)
+static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
+ struct iucv_event *ev = arg;
struct iucv_connection *conn = ev->conn;
- iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data;
+ struct iucv_message *msg = ev->data;
+ struct iucv_message txmsg;
struct netiucv_priv *privptr = NULL;
- /* Shut up, gcc! skb is always below 2G. */
- __u32 single_flag = eib->ipmsgtag;
- __u32 txbytes = 0;
- __u32 txpackets = 0;
- __u32 stat_maxcq = 0;
+ u32 single_flag = msg->tag;
+ u32 txbytes = 0;
+ u32 txpackets = 0;
+ u32 stat_maxcq = 0;
struct sk_buff *skb;
unsigned long saveflags;
- ll_header header;
+ struct ll_header header;
+ int rc;
IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
- if (conn && conn->netdev && conn->netdev->priv)
- privptr = (struct netiucv_priv *)conn->netdev->priv;
+ if (conn && conn->netdev)
+ privptr = netdev_priv(conn->netdev);
conn->prof.tx_pending--;
if (single_flag) {
if ((skb = skb_dequeue(&conn->commit_queue))) {
@@ -688,56 +754,55 @@ conn_action_txdone(fsm_instance *fi, int event, void *arg)
conn->prof.maxmulti = conn->collect_len;
conn->collect_len = 0;
spin_unlock_irqrestore(&conn->collect_lock, saveflags);
- if (conn->tx_buff->len) {
- int rc;
-
- header.next = 0;
- memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,
- NETIUCV_HDRLEN);
+ if (conn->tx_buff->len == 0) {
+ fsm_newstate(fi, CONN_STATE_IDLE);
+ return;
+ }
- conn->prof.send_stamp = xtime;
- rc = iucv_send(conn->pathid, NULL, 0, 0, 0, 0,
+ header.next = 0;
+ memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
+ conn->prof.send_stamp = xtime;
+ txmsg.class = 0;
+ txmsg.tag = 0;
+ rc = iucv_message_send(conn->path, &txmsg, 0, 0,
conn->tx_buff->data, conn->tx_buff->len);
- conn->prof.doios_multi++;
- conn->prof.txlen += conn->tx_buff->len;
- conn->prof.tx_pending++;
- if (conn->prof.tx_pending > conn->prof.tx_max_pending)
- conn->prof.tx_max_pending = conn->prof.tx_pending;
- if (rc) {
- conn->prof.tx_pending--;
- fsm_newstate(fi, CONN_STATE_IDLE);
- if (privptr)
- privptr->stats.tx_errors += txpackets;
- PRINT_WARN("iucv_send returned %08x\n", rc);
- IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
- } else {
- if (privptr) {
- privptr->stats.tx_packets += txpackets;
- privptr->stats.tx_bytes += txbytes;
- }
- if (stat_maxcq > conn->prof.maxcqueue)
- conn->prof.maxcqueue = stat_maxcq;
- }
- } else
+ conn->prof.doios_multi++;
+ conn->prof.txlen += conn->tx_buff->len;
+ conn->prof.tx_pending++;
+ if (conn->prof.tx_pending > conn->prof.tx_max_pending)
+ conn->prof.tx_max_pending = conn->prof.tx_pending;
+ if (rc) {
+ conn->prof.tx_pending--;
fsm_newstate(fi, CONN_STATE_IDLE);
+ if (privptr)
+ privptr->stats.tx_errors += txpackets;
+ PRINT_WARN("iucv_send returned %08x\n", rc);
+ IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
+ } else {
+ if (privptr) {
+ privptr->stats.tx_packets += txpackets;
+ privptr->stats.tx_bytes += txbytes;
+ }
+ if (stat_maxcq > conn->prof.maxcqueue)
+ conn->prof.maxcqueue = stat_maxcq;
+ }
}
-static void
-conn_action_connaccept(fsm_instance *fi, int event, void *arg)
+static void conn_action_connaccept(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
+ struct iucv_event *ev = arg;
struct iucv_connection *conn = ev->conn;
- iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
+ struct iucv_path *path = ev->data;
struct net_device *netdev = conn->netdev;
- struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
+ struct netiucv_priv *privptr = netdev_priv(netdev);
int rc;
- __u16 msglimit;
- __u8 udata[16];
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- rc = iucv_accept(eib->ippathid, NETIUCV_QUEUELEN_DEFAULT, udata, 0,
- conn->handle, conn, NULL, &msglimit);
+ conn->path = path;
+ path->msglim = NETIUCV_QUEUELEN_DEFAULT;
+ path->flags = 0;
+ rc = iucv_path_accept(path, &netiucv_handler, NULL, conn);
if (rc) {
PRINT_WARN("%s: IUCV accept failed with error %d\n",
netdev->name, rc);
@@ -745,183 +810,126 @@ conn_action_connaccept(fsm_instance *fi, int event, void *arg)
return;
}
fsm_newstate(fi, CONN_STATE_IDLE);
- conn->pathid = eib->ippathid;
- netdev->tx_queue_len = msglimit;
+ netdev->tx_queue_len = conn->path->msglim;
fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
}
-static void
-conn_action_connreject(fsm_instance *fi, int event, void *arg)
+static void conn_action_connreject(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
- struct net_device *netdev = conn->netdev;
- iucv_ConnectionPending *eib = (iucv_ConnectionPending *)ev->data;
- __u8 udata[16];
+ struct iucv_event *ev = arg;
+ struct iucv_path *path = ev->data;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-
- iucv_sever(eib->ippathid, udata);
- if (eib->ippathid != conn->pathid) {
- PRINT_INFO("%s: IR Connection Pending; "
- "pathid %d does not match original pathid %d\n",
- netdev->name, eib->ippathid, conn->pathid);
- IUCV_DBF_TEXT_(data, 2,
- "connreject: IR pathid %d, conn. pathid %d\n",
- eib->ippathid, conn->pathid);
- iucv_sever(conn->pathid, udata);
- }
+ iucv_path_sever(path, NULL);
}
-static void
-conn_action_connack(fsm_instance *fi, int event, void *arg)
+static void conn_action_connack(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
- iucv_ConnectionComplete *eib = (iucv_ConnectionComplete *)ev->data;
+ struct iucv_connection *conn = arg;
struct net_device *netdev = conn->netdev;
- struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
+ struct netiucv_priv *privptr = netdev_priv(netdev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-
fsm_deltimer(&conn->timer);
fsm_newstate(fi, CONN_STATE_IDLE);
- if (eib->ippathid != conn->pathid) {
- PRINT_INFO("%s: IR Connection Complete; "
- "pathid %d does not match original pathid %d\n",
- netdev->name, eib->ippathid, conn->pathid);
- IUCV_DBF_TEXT_(data, 2,
- "connack: IR pathid %d, conn. pathid %d\n",
- eib->ippathid, conn->pathid);
- conn->pathid = eib->ippathid;
- }
- netdev->tx_queue_len = eib->ipmsglim;
+ netdev->tx_queue_len = conn->path->msglim;
fsm_event(privptr->fsm, DEV_EVENT_CONUP, netdev);
}
-static void
-conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
+static void conn_action_conntimsev(fsm_instance *fi, int event, void *arg)
{
- struct iucv_connection *conn = (struct iucv_connection *)arg;
- __u8 udata[16];
+ struct iucv_connection *conn = arg;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
-
fsm_deltimer(&conn->timer);
- iucv_sever(conn->pathid, udata);
+ iucv_path_sever(conn->path, NULL);
fsm_newstate(fi, CONN_STATE_STARTWAIT);
}
-static void
-conn_action_connsever(fsm_instance *fi, int event, void *arg)
+static void conn_action_connsever(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
+ struct iucv_connection *conn = arg;
struct net_device *netdev = conn->netdev;
- struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
- __u8 udata[16];
+ struct netiucv_priv *privptr = netdev_priv(netdev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
fsm_deltimer(&conn->timer);
- iucv_sever(conn->pathid, udata);
+ iucv_path_sever(conn->path, NULL);
PRINT_INFO("%s: Remote dropped connection\n", netdev->name);
IUCV_DBF_TEXT(data, 2,
- "conn_action_connsever: Remote dropped connection\n");
+ "conn_action_connsever: Remote dropped connection\n");
fsm_newstate(fi, CONN_STATE_STARTWAIT);
fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
}
-static void
-conn_action_start(fsm_instance *fi, int event, void *arg)
+static void conn_action_start(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
- __u16 msglimit;
+ struct iucv_connection *conn = arg;
int rc;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- if (!conn->handle) {
- IUCV_DBF_TEXT(trace, 5, "calling iucv_register_program\n");
- conn->handle =
- iucv_register_program(iucvMagic, conn->userid,
- netiucv_mask,
- &netiucv_ops, conn);
- fsm_newstate(fi, CONN_STATE_STARTWAIT);
- if (!conn->handle) {
- fsm_newstate(fi, CONN_STATE_REGERR);
- conn->handle = NULL;
- IUCV_DBF_TEXT(setup, 2,
- "NULL from iucv_register_program\n");
- return;
- }
-
- PRINT_DEBUG("%s('%s'): registered successfully\n",
- conn->netdev->name, conn->userid);
- }
-
+ fsm_newstate(fi, CONN_STATE_STARTWAIT);
PRINT_DEBUG("%s('%s'): connecting ...\n",
- conn->netdev->name, conn->userid);
+ conn->netdev->name, conn->userid);
- /* We must set the state before calling iucv_connect because the callback
- * handler could be called at any point after the connection request is
- * sent */
+ /*
+ * We must set the state before calling iucv_connect because the
+ * callback handler could be called at any point after the connection
+ * request is sent
+ */
fsm_newstate(fi, CONN_STATE_SETUPWAIT);
- rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
- conn->userid, iucv_host, 0, NULL, &msglimit,
- conn->handle, conn);
+ conn->path = iucv_path_alloc(NETIUCV_QUEUELEN_DEFAULT, 0, GFP_KERNEL);
+ rc = iucv_path_connect(conn->path, &netiucv_handler, conn->userid,
+ NULL, iucvMagic, conn);
switch (rc) {
- case 0:
- conn->netdev->tx_queue_len = msglimit;
- fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
- CONN_EVENT_TIMER, conn);
- return;
- case 11:
- PRINT_INFO("%s: User %s is currently not available.\n",
- conn->netdev->name,
- netiucv_printname(conn->userid));
- fsm_newstate(fi, CONN_STATE_STARTWAIT);
- return;
- case 12:
- PRINT_INFO("%s: User %s is currently not ready.\n",
- conn->netdev->name,
- netiucv_printname(conn->userid));
- fsm_newstate(fi, CONN_STATE_STARTWAIT);
- return;
- case 13:
- PRINT_WARN("%s: Too many IUCV connections.\n",
- conn->netdev->name);
- fsm_newstate(fi, CONN_STATE_CONNERR);
- break;
- case 14:
- PRINT_WARN(
- "%s: User %s has too many IUCV connections.\n",
- conn->netdev->name,
- netiucv_printname(conn->userid));
- fsm_newstate(fi, CONN_STATE_CONNERR);
- break;
- case 15:
- PRINT_WARN(
- "%s: No IUCV authorization in CP directory.\n",
- conn->netdev->name);
- fsm_newstate(fi, CONN_STATE_CONNERR);
- break;
- default:
- PRINT_WARN("%s: iucv_connect returned error %d\n",
- conn->netdev->name, rc);
- fsm_newstate(fi, CONN_STATE_CONNERR);
- break;
+ case 0:
+ conn->netdev->tx_queue_len = conn->path->msglim;
+ fsm_addtimer(&conn->timer, NETIUCV_TIMEOUT_5SEC,
+ CONN_EVENT_TIMER, conn);
+ return;
+ case 11:
+ PRINT_INFO("%s: User %s is currently not available.\n",
+ conn->netdev->name,
+ netiucv_printname(conn->userid));
+ fsm_newstate(fi, CONN_STATE_STARTWAIT);
+ break;
+ case 12:
+ PRINT_INFO("%s: User %s is currently not ready.\n",
+ conn->netdev->name,
+ netiucv_printname(conn->userid));
+ fsm_newstate(fi, CONN_STATE_STARTWAIT);
+ break;
+ case 13:
+ PRINT_WARN("%s: Too many IUCV connections.\n",
+ conn->netdev->name);
+ fsm_newstate(fi, CONN_STATE_CONNERR);
+ break;
+ case 14:
+ PRINT_WARN("%s: User %s has too many IUCV connections.\n",
+ conn->netdev->name,
+ netiucv_printname(conn->userid));
+ fsm_newstate(fi, CONN_STATE_CONNERR);
+ break;
+ case 15:
+ PRINT_WARN("%s: No IUCV authorization in CP directory.\n",
+ conn->netdev->name);
+ fsm_newstate(fi, CONN_STATE_CONNERR);
+ break;
+ default:
+ PRINT_WARN("%s: iucv_connect returned error %d\n",
+ conn->netdev->name, rc);
+ fsm_newstate(fi, CONN_STATE_CONNERR);
+ break;
}
IUCV_DBF_TEXT_(setup, 5, "iucv_connect rc is %d\n", rc);
- IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n");
- iucv_unregister_program(conn->handle);
- conn->handle = NULL;
+ kfree(conn->path);
+ conn->path = NULL;
}
-static void
-netiucv_purge_skb_queue(struct sk_buff_head *q)
+static void netiucv_purge_skb_queue(struct sk_buff_head *q)
{
struct sk_buff *skb;
@@ -931,36 +939,34 @@ netiucv_purge_skb_queue(struct sk_buff_head *q)
}
}
-static void
-conn_action_stop(fsm_instance *fi, int event, void *arg)
+static void conn_action_stop(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
+ struct iucv_event *ev = arg;
struct iucv_connection *conn = ev->conn;
struct net_device *netdev = conn->netdev;
- struct netiucv_priv *privptr = (struct netiucv_priv *)netdev->priv;
+ struct netiucv_priv *privptr = netdev_priv(netdev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
fsm_deltimer(&conn->timer);
fsm_newstate(fi, CONN_STATE_STOPPED);
netiucv_purge_skb_queue(&conn->collect_queue);
- if (conn->handle)
- IUCV_DBF_TEXT(trace, 5, "calling iucv_unregister_program\n");
- iucv_unregister_program(conn->handle);
- conn->handle = NULL;
+ if (conn->path) {
+ IUCV_DBF_TEXT(trace, 5, "calling iucv_path_sever\n");
+ iucv_path_sever(conn->path, iucvMagic);
+ kfree(conn->path);
+ conn->path = NULL;
+ }
netiucv_purge_skb_queue(&conn->commit_queue);
fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev);
}
-static void
-conn_action_inval(fsm_instance *fi, int event, void *arg)
+static void conn_action_inval(fsm_instance *fi, int event, void *arg)
{
- struct iucv_event *ev = (struct iucv_event *)arg;
- struct iucv_connection *conn = ev->conn;
+ struct iucv_connection *conn = arg;
struct net_device *netdev = conn->netdev;
- PRINT_WARN("%s: Cannot connect without username\n",
- netdev->name);
+ PRINT_WARN("%s: Cannot connect without username\n", netdev->name);
IUCV_DBF_TEXT(data, 2, "conn_action_inval called\n");
}
@@ -999,29 +1005,27 @@ static const fsm_node conn_fsm[] = {
static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
-/**
+/*
* Actions for interface - statemachine.
- *****************************************************************************/
+ */
/**
- * Startup connection by sending CONN_EVENT_START to it.
+ * dev_action_start
+ * @fi: An instance of an interface statemachine.
+ * @event: The event, just happened.
+ * @arg: Generic pointer, casted from struct net_device * upon call.
*
- * @param fi An instance of an interface statemachine.
- * @param event The event, just happened.
- * @param arg Generic pointer, casted from struct net_device * upon call.
+ * Startup connection by sending CONN_EVENT_START to it.
*/
-static void
-dev_action_start(fsm_instance *fi, int event, void *arg)
+static void dev_action_start(fsm_instance *fi, int event, void *arg)
{
- struct net_device *dev = (struct net_device *)arg;
- struct netiucv_priv *privptr = dev->priv;
- struct iucv_event ev;
+ struct net_device *dev = arg;
+ struct netiucv_priv *privptr = netdev_priv(dev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- ev.conn = privptr->conn;
fsm_newstate(fi, DEV_STATE_STARTWAIT);
- fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev);
+ fsm_event(privptr->conn->fsm, CONN_EVENT_START, privptr->conn);
}
/**
@@ -1034,8 +1038,8 @@ dev_action_start(fsm_instance *fi, int event, void *arg)
static void
dev_action_stop(fsm_instance *fi, int event, void *arg)
{
- struct net_device *dev = (struct net_device *)arg;
- struct netiucv_priv *privptr = dev->priv;
+ struct net_device *dev = arg;
+ struct netiucv_priv *privptr = netdev_priv(dev);
struct iucv_event ev;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
@@ -1057,8 +1061,8 @@ dev_action_stop(fsm_instance *fi, int event, void *arg)
static void
dev_action_connup(fsm_instance *fi, int event, void *arg)
{
- struct net_device *dev = (struct net_device *)arg;
- struct netiucv_priv *privptr = dev->priv;
+ struct net_device *dev = arg;
+ struct netiucv_priv *privptr = netdev_priv(dev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
@@ -1131,11 +1135,13 @@ static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node);
*
* @return 0 on success, -ERRNO on failure. (Never fails.)
*/
-static int
-netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
+static int netiucv_transmit_skb(struct iucv_connection *conn,
+ struct sk_buff *skb)
+{
+ struct iucv_message msg;
unsigned long saveflags;
- ll_header header;
- int rc = 0;
+ struct ll_header header;
+ int rc;
if (fsm_getstate(conn->fsm) != CONN_STATE_IDLE) {
int l = skb->len + NETIUCV_HDRLEN;
@@ -1145,11 +1151,12 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
(conn->max_buffsize - NETIUCV_HDRLEN)) {
rc = -EBUSY;
IUCV_DBF_TEXT(data, 2,
- "EBUSY from netiucv_transmit_skb\n");
+ "EBUSY from netiucv_transmit_skb\n");
} else {
atomic_inc(&skb->users);
skb_queue_tail(&conn->collect_queue, skb);
conn->collect_len += l;
+ rc = 0;
}
spin_unlock_irqrestore(&conn->collect_lock, saveflags);
} else {
@@ -1188,9 +1195,10 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
fsm_newstate(conn->fsm, CONN_STATE_TX);
conn->prof.send_stamp = xtime;
- rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
- 0, nskb->data, nskb->len);
- /* Shut up, gcc! nskb is always below 2G. */
+ msg.tag = 1;
+ msg.class = 0;
+ rc = iucv_message_send(conn->path, &msg, 0, 0,
+ nskb->data, nskb->len);
conn->prof.doios_single++;
conn->prof.txlen += skb->len;
conn->prof.tx_pending++;
@@ -1200,7 +1208,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
struct netiucv_priv *privptr;
fsm_newstate(conn->fsm, CONN_STATE_IDLE);
conn->prof.tx_pending--;
- privptr = (struct netiucv_priv *)conn->netdev->priv;
+ privptr = netdev_priv(conn->netdev);
if (privptr)
privptr->stats.tx_errors++;
if (copied)
@@ -1226,9 +1234,9 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
return rc;
}
-/**
+/*
* Interface API for upper network layers
- *****************************************************************************/
+ */
/**
* Open an interface.
@@ -1238,9 +1246,11 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
*
* @return 0 on success, -ERRNO on failure. (Never fails.)
*/
-static int
-netiucv_open(struct net_device *dev) {
- fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_START,dev);
+static int netiucv_open(struct net_device *dev)
+{
+ struct netiucv_priv *priv = netdev_priv(dev);
+
+ fsm_event(priv->fsm, DEV_EVENT_START, dev);
return 0;
}
@@ -1252,9 +1262,11 @@ netiucv_open(struct net_device *dev) {
*
* @return 0 on success, -ERRNO on failure. (Never fails.)
*/
-static int
-netiucv_close(struct net_device *dev) {
- fsm_event(((struct netiucv_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev);
+static int netiucv_close(struct net_device *dev)
+{
+ struct netiucv_priv *priv = netdev_priv(dev);
+
+ fsm_event(priv->fsm, DEV_EVENT_STOP, dev);
return 0;
}
@@ -1271,8 +1283,8 @@ netiucv_close(struct net_device *dev) {
*/
static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
{
- int rc = 0;
- struct netiucv_priv *privptr = dev->priv;
+ struct netiucv_priv *privptr = netdev_priv(dev);
+ int rc;
IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
/**
@@ -1312,40 +1324,41 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
return -EBUSY;
}
dev->trans_start = jiffies;
- if (netiucv_transmit_skb(privptr->conn, skb))
- rc = 1;
+ rc = netiucv_transmit_skb(privptr->conn, skb) != 0;
netiucv_clear_busy(dev);
return rc;
}
/**
- * Returns interface statistics of a device.
+ * netiucv_stats
+ * @dev: Pointer to interface struct.
*
- * @param dev Pointer to interface struct.
+ * Returns interface statistics of a device.
*
- * @return Pointer to stats struct of this interface.
+ * Returns pointer to stats struct of this interface.
*/
-static struct net_device_stats *
-netiucv_stats (struct net_device * dev)
+static struct net_device_stats *netiucv_stats (struct net_device * dev)
{
+ struct netiucv_priv *priv = netdev_priv(dev);
+
IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
- return &((struct netiucv_priv *)dev->priv)->stats;
+ return &priv->stats;
}
/**
- * Sets MTU of an interface.
+ * netiucv_change_mtu
+ * @dev: Pointer to interface struct.
+ * @new_mtu: The new MTU to use for this interface.
*
- * @param dev Pointer to interface struct.
- * @param new_mtu The new MTU to use for this interface.
+ * Sets MTU of an interface.
*
- * @return 0 on success, -EINVAL if MTU is out of valid range.
+ * Returns 0 on success, -EINVAL if MTU is out of valid range.
* (valid range is 576 .. NETIUCV_MTU_MAX).
*/
-static int
-netiucv_change_mtu (struct net_device * dev, int new_mtu)
+static int netiucv_change_mtu(struct net_device * dev, int new_mtu)
{
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- if ((new_mtu < 576) || (new_mtu > NETIUCV_MTU_MAX)) {
+ if (new_mtu < 576 || new_mtu > NETIUCV_MTU_MAX) {
IUCV_DBF_TEXT(setup, 2, "given MTU out of valid range\n");
return -EINVAL;
}
@@ -1353,12 +1366,12 @@ netiucv_change_mtu (struct net_device * dev, int new_mtu)
return 0;
}
-/**
+/*
* attributes in sysfs
- *****************************************************************************/
+ */
-static ssize_t
-user_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t user_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1366,8 +1379,8 @@ user_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
}
-static ssize_t
-user_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t user_write(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
struct net_device *ndev = priv->conn->netdev;
@@ -1375,80 +1388,70 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf,
char *tmp;
char username[9];
int i;
- struct iucv_connection **clist = &iucv_conns.iucv_connections;
- unsigned long flags;
+ struct iucv_connection *cp;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- if (count>9) {
- PRINT_WARN("netiucv: username too long (%d)!\n", (int)count);
+ if (count > 9) {
+ PRINT_WARN("netiucv: username too long (%d)!\n", (int) count);
IUCV_DBF_TEXT_(setup, 2,
- "%d is length of username\n", (int)count);
+ "%d is length of username\n", (int) count);
return -EINVAL;
}
tmp = strsep((char **) &buf, "\n");
- for (i=0, p=tmp; i<8 && *p; i++, p++) {
- if (isalnum(*p) || (*p == '$'))
+ for (i = 0, p = tmp; i < 8 && *p; i++, p++) {
+ if (isalnum(*p) || (*p == '$')) {
username[i]= toupper(*p);
- else if (*p == '\n') {
+ continue;
+ }
+ if (*p == '\n') {
/* trailing lf, grr */
break;
- } else {
- PRINT_WARN("netiucv: Invalid char %c in username!\n",
- *p);
- IUCV_DBF_TEXT_(setup, 2,
- "username: invalid character %c\n",
- *p);
- return -EINVAL;
}
+ PRINT_WARN("netiucv: Invalid char %c in username!\n", *p);
+ IUCV_DBF_TEXT_(setup, 2,
+ "username: invalid character %c\n", *p);
+ return -EINVAL;
}
- while (i<8)
+ while (i < 8)
username[i++] = ' ';
username[8] = '\0';
- if (memcmp(username, priv->conn->userid, 9)) {
- /* username changed */
- if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
- PRINT_WARN(
- "netiucv: device %s active, connected to %s\n",
- dev->bus_id, priv->conn->userid);
- PRINT_WARN("netiucv: user cannot be updated\n");
- IUCV_DBF_TEXT(setup, 2, "user_write: device active\n");
- return -EBUSY;
+ if (memcmp(username, priv->conn->userid, 9) &&
+ (ndev->flags & (IFF_UP | IFF_RUNNING))) {
+ /* username changed while the interface is active. */
+ PRINT_WARN("netiucv: device %s active, connected to %s\n",
+ dev->bus_id, priv->conn->userid);
+ PRINT_WARN("netiucv: user cannot be updated\n");
+ IUCV_DBF_TEXT(setup, 2, "user_write: device active\n");
+ return -EBUSY;
+ }
+ read_lock_bh(&iucv_connection_rwlock);
+ list_for_each_entry(cp, &iucv_connection_list, list) {
+ if (!strncmp(username, cp->userid, 9) && cp->netdev != ndev) {
+ read_unlock_bh(&iucv_connection_rwlock);
+ PRINT_WARN("netiucv: Connection to %s already "
+ "exists\n", username);
+ return -EEXIST;
}
}
- read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
- while (*clist) {
- if (!strncmp(username, (*clist)->userid, 9) ||
- ((*clist)->netdev != ndev))
- break;
- clist = &((*clist)->next);
- }
- read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
- if (*clist) {
- PRINT_WARN("netiucv: Connection to %s already exists\n",
- username);
- return -EEXIST;
- }
+ read_unlock_bh(&iucv_connection_rwlock);
memcpy(priv->conn->userid, username, 9);
-
return count;
-
}
static DEVICE_ATTR(user, 0644, user_show, user_write);
-static ssize_t
-buffer_show (struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct netiucv_priv *priv = dev->driver_data;
+static ssize_t buffer_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
+{ struct netiucv_priv *priv = dev->driver_data;
IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
return sprintf(buf, "%d\n", priv->conn->max_buffsize);
}
-static ssize_t
-buffer_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
struct net_device *ndev = priv->conn->netdev;
@@ -1502,8 +1505,8 @@ buffer_write (struct device *dev, struct device_attribute *attr, const char *buf
static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
-static ssize_t
-dev_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t dev_fsm_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1513,8 +1516,8 @@ dev_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL);
-static ssize_t
-conn_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t conn_fsm_show (struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1524,8 +1527,8 @@ conn_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL);
-static ssize_t
-maxmulti_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t maxmulti_show (struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1533,8 +1536,9 @@ maxmulti_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%ld\n", priv->conn->prof.maxmulti);
}
-static ssize_t
-maxmulti_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t maxmulti_write (struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1545,8 +1549,8 @@ maxmulti_write (struct device *dev, struct device_attribute *attr, const char *b
static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write);
-static ssize_t
-maxcq_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t maxcq_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1554,8 +1558,8 @@ maxcq_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%ld\n", priv->conn->prof.maxcqueue);
}
-static ssize_t
-maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t maxcq_write (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1566,8 +1570,8 @@ maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf,
static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write);
-static ssize_t
-sdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t sdoio_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1575,8 +1579,8 @@ sdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%ld\n", priv->conn->prof.doios_single);
}
-static ssize_t
-sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t sdoio_write (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1587,8 +1591,8 @@ sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf,
static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write);
-static ssize_t
-mdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t mdoio_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1596,8 +1600,8 @@ mdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%ld\n", priv->conn->prof.doios_multi);
}
-static ssize_t
-mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t mdoio_write (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1608,8 +1612,8 @@ mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf,
static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write);
-static ssize_t
-txlen_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t txlen_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1617,8 +1621,8 @@ txlen_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%ld\n", priv->conn->prof.txlen);
}
-static ssize_t
-txlen_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t txlen_write (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1629,8 +1633,8 @@ txlen_write (struct device *dev, struct device_attribute *attr, const char *buf,
static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write);
-static ssize_t
-txtime_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t txtime_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1638,8 +1642,8 @@ txtime_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%ld\n", priv->conn->prof.tx_time);
}
-static ssize_t
-txtime_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t txtime_write (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1650,8 +1654,8 @@ txtime_write (struct device *dev, struct device_attribute *attr, const char *buf
static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write);
-static ssize_t
-txpend_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t txpend_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1659,8 +1663,8 @@ txpend_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending);
}
-static ssize_t
-txpend_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t txpend_write (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1671,8 +1675,8 @@ txpend_write (struct device *dev, struct device_attribute *attr, const char *buf
static DEVICE_ATTR(tx_pending, 0644, txpend_show, txpend_write);
-static ssize_t
-txmpnd_show (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t txmpnd_show (struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1680,8 +1684,8 @@ txmpnd_show (struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending);
}
-static ssize_t
-txmpnd_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t txmpnd_write (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1721,8 +1725,7 @@ static struct attribute_group netiucv_stat_attr_group = {
.attrs = netiucv_stat_attrs,
};
-static inline int
-netiucv_add_files(struct device *dev)
+static inline int netiucv_add_files(struct device *dev)
{
int ret;
@@ -1736,18 +1739,16 @@ netiucv_add_files(struct device *dev)
return ret;
}
-static inline void
-netiucv_remove_files(struct device *dev)
+static inline void netiucv_remove_files(struct device *dev)
{
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
sysfs_remove_group(&dev->kobj, &netiucv_attr_group);
}
-static int
-netiucv_register_device(struct net_device *ndev)
+static int netiucv_register_device(struct net_device *ndev)
{
- struct netiucv_priv *priv = ndev->priv;
+ struct netiucv_priv *priv = netdev_priv(ndev);
struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL);
int ret;
@@ -1786,8 +1787,7 @@ out_unreg:
return ret;
}
-static void
-netiucv_unregister_device(struct device *dev)
+static void netiucv_unregister_device(struct device *dev)
{
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
netiucv_remove_files(dev);
@@ -1798,107 +1798,89 @@ netiucv_unregister_device(struct device *dev)
* Allocate and initialize a new connection structure.
* Add it to the list of netiucv connections;
*/
-static struct iucv_connection *
-netiucv_new_connection(struct net_device *dev, char *username)
-{
- unsigned long flags;
- struct iucv_connection **clist = &iucv_conns.iucv_connections;
- struct iucv_connection *conn =
- kzalloc(sizeof(struct iucv_connection), GFP_KERNEL);
-
- if (conn) {
- skb_queue_head_init(&conn->collect_queue);
- skb_queue_head_init(&conn->commit_queue);
- spin_lock_init(&conn->collect_lock);
- conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
- conn->netdev = dev;
-
- conn->rx_buff = alloc_skb(NETIUCV_BUFSIZE_DEFAULT,
- GFP_KERNEL | GFP_DMA);
- if (!conn->rx_buff) {
- kfree(conn);
- return NULL;
- }
- conn->tx_buff = alloc_skb(NETIUCV_BUFSIZE_DEFAULT,
- GFP_KERNEL | GFP_DMA);
- if (!conn->tx_buff) {
- kfree_skb(conn->rx_buff);
- kfree(conn);
- return NULL;
- }
- conn->fsm = init_fsm("netiucvconn", conn_state_names,
- conn_event_names, NR_CONN_STATES,
- NR_CONN_EVENTS, conn_fsm, CONN_FSM_LEN,
- GFP_KERNEL);
- if (!conn->fsm) {
- kfree_skb(conn->tx_buff);
- kfree_skb(conn->rx_buff);
- kfree(conn);
- return NULL;
- }
- fsm_settimer(conn->fsm, &conn->timer);
- fsm_newstate(conn->fsm, CONN_STATE_INVALID);
-
- if (username) {
- memcpy(conn->userid, username, 9);
- fsm_newstate(conn->fsm, CONN_STATE_STOPPED);
- }
+static struct iucv_connection *netiucv_new_connection(struct net_device *dev,
+ char *username)
+{
+ struct iucv_connection *conn;
- write_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
- conn->next = *clist;
- *clist = conn;
- write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+ conn = kzalloc(sizeof(*conn), GFP_KERNEL);
+ if (!conn)
+ goto out;
+ skb_queue_head_init(&conn->collect_queue);
+ skb_queue_head_init(&conn->commit_queue);
+ spin_lock_init(&conn->collect_lock);
+ conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT;
+ conn->netdev = dev;
+
+ conn->rx_buff = alloc_skb(conn->max_buffsize, GFP_KERNEL | GFP_DMA);
+ if (!conn->rx_buff)
+ goto out_conn;
+ conn->tx_buff = alloc_skb(conn->max_buffsize, GFP_KERNEL | GFP_DMA);
+ if (!conn->tx_buff)
+ goto out_rx;
+ conn->fsm = init_fsm("netiucvconn", conn_state_names,
+ conn_event_names, NR_CONN_STATES,
+ NR_CONN_EVENTS, conn_fsm, CONN_FSM_LEN,
+ GFP_KERNEL);
+ if (!conn->fsm)
+ goto out_tx;
+
+ fsm_settimer(conn->fsm, &conn->timer);
+ fsm_newstate(conn->fsm, CONN_STATE_INVALID);
+
+ if (username) {
+ memcpy(conn->userid, username, 9);
+ fsm_newstate(conn->fsm, CONN_STATE_STOPPED);
}
+
+ write_lock_bh(&iucv_connection_rwlock);
+ list_add_tail(&conn->list, &iucv_connection_list);
+ write_unlock_bh(&iucv_connection_rwlock);
return conn;
+
+out_tx:
+ kfree_skb(conn->tx_buff);
+out_rx:
+ kfree_skb(conn->rx_buff);
+out_conn:
+ kfree(conn);
+out:
+ return NULL;
}
/**
* Release a connection structure and remove it from the
* list of netiucv connections.
*/
-static void
-netiucv_remove_connection(struct iucv_connection *conn)
+static void netiucv_remove_connection(struct iucv_connection *conn)
{
- struct iucv_connection **clist = &iucv_conns.iucv_connections;
- unsigned long flags;
-
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- if (conn == NULL)
- return;
- write_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
- while (*clist) {
- if (*clist == conn) {
- *clist = conn->next;
- write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
- if (conn->handle) {
- iucv_unregister_program(conn->handle);
- conn->handle = NULL;
- }
- fsm_deltimer(&conn->timer);
- kfree_fsm(conn->fsm);
- kfree_skb(conn->rx_buff);
- kfree_skb(conn->tx_buff);
- return;
- }
- clist = &((*clist)->next);
+ write_lock_bh(&iucv_connection_rwlock);
+ list_del_init(&conn->list);
+ write_unlock_bh(&iucv_connection_rwlock);
+ if (conn->path) {
+ iucv_path_sever(conn->path, iucvMagic);
+ kfree(conn->path);
+ conn->path = NULL;
}
- write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+ fsm_deltimer(&conn->timer);
+ kfree_fsm(conn->fsm);
+ kfree_skb(conn->rx_buff);
+ kfree_skb(conn->tx_buff);
}
/**
* Release everything of a net device.
*/
-static void
-netiucv_free_netdevice(struct net_device *dev)
+static void netiucv_free_netdevice(struct net_device *dev)
{
- struct netiucv_priv *privptr;
+ struct netiucv_priv *privptr = netdev_priv(dev);
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
if (!dev)
return;
- privptr = (struct netiucv_priv *)dev->priv;
if (privptr) {
if (privptr->conn)
netiucv_remove_connection(privptr->conn);
@@ -1913,11 +1895,8 @@ netiucv_free_netdevice(struct net_device *dev)
/**
* Initialize a net device. (Called from kernel in alloc_netdev())
*/
-static void
-netiucv_setup_netdevice(struct net_device *dev)
+static void netiucv_setup_netdevice(struct net_device *dev)
{
- memset(dev->priv, 0, sizeof(struct netiucv_priv));
-
dev->mtu = NETIUCV_MTU_DEFAULT;
dev->hard_start_xmit = netiucv_tx;
dev->open = netiucv_open;
@@ -1936,8 +1915,7 @@ netiucv_setup_netdevice(struct net_device *dev)
/**
* Allocate and initialize everything of a net device.
*/
-static struct net_device *
-netiucv_init_netdevice(char *username)
+static struct net_device *netiucv_init_netdevice(char *username)
{
struct netiucv_priv *privptr;
struct net_device *dev;
@@ -1946,40 +1924,40 @@ netiucv_init_netdevice(char *username)
netiucv_setup_netdevice);
if (!dev)
return NULL;
- if (dev_alloc_name(dev, dev->name) < 0) {
- free_netdev(dev);
- return NULL;
- }
+ if (dev_alloc_name(dev, dev->name) < 0)
+ goto out_netdev;
- privptr = (struct netiucv_priv *)dev->priv;
+ privptr = netdev_priv(dev);
privptr->fsm = init_fsm("netiucvdev", dev_state_names,
dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
- if (!privptr->fsm) {
- free_netdev(dev);
- return NULL;
- }
+ if (!privptr->fsm)
+ goto out_netdev;
+
privptr->conn = netiucv_new_connection(dev, username);
if (!privptr->conn) {
- kfree_fsm(privptr->fsm);
- free_netdev(dev);
IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_new_connection\n");
- return NULL;
+ goto out_fsm;
}
fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
-
return dev;
+
+out_fsm:
+ kfree_fsm(privptr->fsm);
+out_netdev:
+ free_netdev(dev);
+ return NULL;
}
-static ssize_t
-conn_write(struct device_driver *drv, const char *buf, size_t count)
+static ssize_t conn_write(struct device_driver *drv,
+ const char *buf, size_t count)
{
- char *p;
+ const char *p;
char username[9];
- int i, ret;
+ int i, rc;
struct net_device *dev;
- struct iucv_connection **clist = &iucv_conns.iucv_connections;
- unsigned long flags;
+ struct netiucv_priv *priv;
+ struct iucv_connection *cp;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
if (count>9) {
@@ -1988,83 +1966,82 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
return -EINVAL;
}
- for (i=0, p=(char *)buf; i<8 && *p; i++, p++) {
- if (isalnum(*p) || (*p == '$'))
- username[i]= toupper(*p);
- else if (*p == '\n') {
+ for (i = 0, p = buf; i < 8 && *p; i++, p++) {
+ if (isalnum(*p) || *p == '$') {
+ username[i] = toupper(*p);
+ continue;
+ }
+ if (*p == '\n')
/* trailing lf, grr */
break;
- } else {
- PRINT_WARN("netiucv: Invalid character in username!\n");
- IUCV_DBF_TEXT_(setup, 2,
- "conn_write: invalid character %c\n", *p);
- return -EINVAL;
- }
+ PRINT_WARN("netiucv: Invalid character in username!\n");
+ IUCV_DBF_TEXT_(setup, 2,
+ "conn_write: invalid character %c\n", *p);
+ return -EINVAL;
}
- while (i<8)
+ while (i < 8)
username[i++] = ' ';
username[8] = '\0';
- read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
- while (*clist) {
- if (!strncmp(username, (*clist)->userid, 9))
- break;
- clist = &((*clist)->next);
- }
- read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
- if (*clist) {
- PRINT_WARN("netiucv: Connection to %s already exists\n",
- username);
- return -EEXIST;
+ read_lock_bh(&iucv_connection_rwlock);
+ list_for_each_entry(cp, &iucv_connection_list, list) {
+ if (!strncmp(username, cp->userid, 9)) {
+ read_unlock_bh(&iucv_connection_rwlock);
+ PRINT_WARN("netiucv: Connection to %s already "
+ "exists\n", username);
+ return -EEXIST;
+ }
}
+ read_unlock_bh(&iucv_connection_rwlock);
+
dev = netiucv_init_netdevice(username);
if (!dev) {
- PRINT_WARN(
- "netiucv: Could not allocate network device structure "
- "for user '%s'\n", netiucv_printname(username));
+ PRINT_WARN("netiucv: Could not allocate network device "
+ "structure for user '%s'\n",
+ netiucv_printname(username));
IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_init_netdevice\n");
return -ENODEV;
}
- if ((ret = netiucv_register_device(dev))) {
+ rc = netiucv_register_device(dev);
+ if (rc) {
IUCV_DBF_TEXT_(setup, 2,
- "ret %d from netiucv_register_device\n", ret);
+ "ret %d from netiucv_register_device\n", rc);
goto out_free_ndev;
}
/* sysfs magic */
- SET_NETDEV_DEV(dev,
- (struct device*)((struct netiucv_priv*)dev->priv)->dev);
+ priv = netdev_priv(dev);
+ SET_NETDEV_DEV(dev, priv->dev);
- if ((ret = register_netdev(dev))) {
- netiucv_unregister_device((struct device*)
- ((struct netiucv_priv*)dev->priv)->dev);
- goto out_free_ndev;
- }
+ rc = register_netdev(dev);
+ if (rc)
+ goto out_unreg;
PRINT_INFO("%s: '%s'\n", dev->name, netiucv_printname(username));
return count;
+out_unreg:
+ netiucv_unregister_device(priv->dev);
out_free_ndev:
PRINT_WARN("netiucv: Could not register '%s'\n", dev->name);
IUCV_DBF_TEXT(setup, 2, "conn_write: could not register\n");
netiucv_free_netdevice(dev);
- return ret;
+ return rc;
}
static DRIVER_ATTR(connection, 0200, NULL, conn_write);
-static ssize_t
-remove_write (struct device_driver *drv, const char *buf, size_t count)
+static ssize_t remove_write (struct device_driver *drv,
+ const char *buf, size_t count)
{
- struct iucv_connection **clist = &iucv_conns.iucv_connections;
- unsigned long flags;
+ struct iucv_connection *cp;
struct net_device *ndev;
struct netiucv_priv *priv;
struct device *dev;
char name[IFNAMSIZ];
- char *p;
+ const char *p;
int i;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
@@ -2072,33 +2049,27 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
if (count >= IFNAMSIZ)
count = IFNAMSIZ - 1;;
- for (i=0, p=(char *)buf; i<count && *p; i++, p++) {
- if ((*p == '\n') || (*p == ' ')) {
+ for (i = 0, p = buf; i < count && *p; i++, p++) {
+ if (*p == '\n' || *p == ' ')
/* trailing lf, grr */
break;
- } else {
- name[i]=*p;
- }
+ name[i] = *p;
}
name[i] = '\0';
- read_lock_irqsave(&iucv_conns.iucv_rwlock, flags);
- while (*clist) {
- ndev = (*clist)->netdev;
- priv = (struct netiucv_priv*)ndev->priv;
+ read_lock_bh(&iucv_connection_rwlock);
+ list_for_each_entry(cp, &iucv_connection_list, list) {
+ ndev = cp->netdev;
+ priv = netdev_priv(ndev);
dev = priv->dev;
-
- if (strncmp(name, ndev->name, count)) {
- clist = &((*clist)->next);
- continue;
- }
- read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+ if (strncmp(name, ndev->name, count))
+ continue;
+ read_unlock_bh(&iucv_connection_rwlock);
if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
- PRINT_WARN(
- "netiucv: net device %s active with peer %s\n",
- ndev->name, priv->conn->userid);
+ PRINT_WARN("netiucv: net device %s active with peer "
+ "%s\n", ndev->name, priv->conn->userid);
PRINT_WARN("netiucv: %s cannot be removed\n",
- ndev->name);
+ ndev->name);
IUCV_DBF_TEXT(data, 2, "remove_write: still active\n");
return -EBUSY;
}
@@ -2106,7 +2077,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
netiucv_unregister_device(dev);
return count;
}
- read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags);
+ read_unlock_bh(&iucv_connection_rwlock);
PRINT_WARN("netiucv: net device %s unknown\n", name);
IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n");
return -EINVAL;
@@ -2114,67 +2085,86 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
static DRIVER_ATTR(remove, 0200, NULL, remove_write);
-static void
-netiucv_banner(void)
+static struct attribute * netiucv_drv_attrs[] = {
+ &driver_attr_connection.attr,
+ &driver_attr_remove.attr,
+ NULL,
+};
+
+static struct attribute_group netiucv_drv_attr_group = {
+ .attrs = netiucv_drv_attrs,
+};
+
+static void netiucv_banner(void)
{
PRINT_INFO("NETIUCV driver initialized\n");
}
-static void __exit
-netiucv_exit(void)
+static void __exit netiucv_exit(void)
{
+ struct iucv_connection *cp;
+ struct net_device *ndev;
+ struct netiucv_priv *priv;
+ struct device *dev;
+
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- while (iucv_conns.iucv_connections) {
- struct net_device *ndev = iucv_conns.iucv_connections->netdev;
- struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv;
- struct device *dev = priv->dev;
+ while (!list_empty(&iucv_connection_list)) {
+ cp = list_entry(iucv_connection_list.next,
+ struct iucv_connection, list);
+ list_del(&cp->list);
+ ndev = cp->netdev;
+ priv = netdev_priv(ndev);
+ dev = priv->dev;
unregister_netdev(ndev);
netiucv_unregister_device(dev);
}
- driver_remove_file(&netiucv_driver, &driver_attr_connection);
- driver_remove_file(&netiucv_driver, &driver_attr_remove);
+ sysfs_remove_group(&netiucv_driver.kobj, &netiucv_drv_attr_group);
driver_unregister(&netiucv_driver);
+ iucv_unregister(&netiucv_handler, 1);
iucv_unregister_dbf_views();
PRINT_INFO("NETIUCV driver unloaded\n");
return;
}
-static int __init
-netiucv_init(void)
+static int __init netiucv_init(void)
{
- int ret;
+ int rc;
- ret = iucv_register_dbf_views();
- if (ret) {
- PRINT_WARN("netiucv_init failed, "
- "iucv_register_dbf_views rc = %d\n", ret);
- return ret;
- }
+ rc = iucv_register_dbf_views();
+ if (rc)
+ goto out;
+ rc = iucv_register(&netiucv_handler, 1);
+ if (rc)
+ goto out_dbf;
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
- ret = driver_register(&netiucv_driver);
- if (ret) {
+ rc = driver_register(&netiucv_driver);
+ if (rc) {
PRINT_ERR("NETIUCV: failed to register driver.\n");
- IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_register\n", ret);
- iucv_unregister_dbf_views();
- return ret;
+ IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_register\n", rc);
+ goto out_iucv;
}
- /* Add entry for specifying connections. */
- ret = driver_create_file(&netiucv_driver, &driver_attr_connection);
- if (!ret) {
- ret = driver_create_file(&netiucv_driver, &driver_attr_remove);
- netiucv_banner();
- rwlock_init(&iucv_conns.iucv_rwlock);
- } else {
- PRINT_ERR("NETIUCV: failed to add driver attribute.\n");
- IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_create_file\n", ret);
- driver_unregister(&netiucv_driver);
- iucv_unregister_dbf_views();
+ rc = sysfs_create_group(&netiucv_driver.kobj, &netiucv_drv_attr_group);
+ if (rc) {
+ PRINT_ERR("NETIUCV: failed to add driver attributes.\n");
+ IUCV_DBF_TEXT_(setup, 2,
+ "ret %d - netiucv_drv_attr_group\n", rc);
+ goto out_driver;
}
- return ret;
+ netiucv_banner();
+ return rc;
+
+out_driver:
+ driver_unregister(&netiucv_driver);
+out_iucv:
+ iucv_unregister(&netiucv_handler, 1);
+out_dbf:
+ iucv_unregister_dbf_views();
+out:
+ return rc;
}
module_init(netiucv_init);
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index b8179c27ceb6..3ccca5871fdf 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -1,7 +1,7 @@
/*
* IUCV special message driver
*
- * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
*
* This program is free software; you can redistribute it and/or modify
@@ -23,10 +23,10 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/device.h>
+#include <net/iucv/iucv.h>
#include <asm/cpcmd.h>
#include <asm/ebcdic.h>
-
-#include "iucv.h"
+#include "smsgiucv.h"
struct smsg_callback {
struct list_head list;
@@ -39,38 +39,46 @@ MODULE_AUTHOR
("(C) 2003 IBM Corporation by Martin Schwidefsky (schwidefsky@de.ibm.com)");
MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver");
-static iucv_handle_t smsg_handle;
-static unsigned short smsg_pathid;
+static struct iucv_path *smsg_path;
+
static DEFINE_SPINLOCK(smsg_list_lock);
static struct list_head smsg_list = LIST_HEAD_INIT(smsg_list);
-static void
-smsg_connection_complete(iucv_ConnectionComplete *eib, void *pgm_data)
+static int smsg_path_pending(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+static void smsg_message_pending(struct iucv_path *, struct iucv_message *);
+
+static struct iucv_handler smsg_handler = {
+ .path_pending = smsg_path_pending,
+ .message_pending = smsg_message_pending,
+};
+
+static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8],
+ u8 ipuser[16])
{
+ if (strncmp(ipvmid, "*MSG ", sizeof(ipvmid)) != 0)
+ return -EINVAL;
+ /* Path pending from *MSG. */
+ return iucv_path_accept(path, &smsg_handler, "SMSGIUCV ", NULL);
}
-
-static void
-smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
+static void smsg_message_pending(struct iucv_path *path,
+ struct iucv_message *msg)
{
struct smsg_callback *cb;
- unsigned char *msg;
+ unsigned char *buffer;
unsigned char sender[9];
- unsigned short len;
int rc, i;
- len = eib->ln1msg2.ipbfln1f;
- msg = kmalloc(len + 1, GFP_ATOMIC|GFP_DMA);
- if (!msg) {
- iucv_reject(eib->ippathid, eib->ipmsgid, eib->iptrgcls);
+ buffer = kmalloc(msg->length + 1, GFP_ATOMIC | GFP_DMA);
+ if (!buffer) {
+ iucv_message_reject(path, msg);
return;
}
- rc = iucv_receive(eib->ippathid, eib->ipmsgid, eib->iptrgcls,
- msg, len, NULL, NULL, NULL);
+ rc = iucv_message_receive(path, msg, 0, buffer, msg->length, NULL);
if (rc == 0) {
- msg[len] = 0;
- EBCASC(msg, len);
- memcpy(sender, msg, 8);
+ buffer[msg->length] = 0;
+ EBCASC(buffer, msg->length);
+ memcpy(sender, buffer, 8);
sender[8] = 0;
/* Remove trailing whitespace from the sender name. */
for (i = 7; i >= 0; i--) {
@@ -80,27 +88,17 @@ smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
}
spin_lock(&smsg_list_lock);
list_for_each_entry(cb, &smsg_list, list)
- if (strncmp(msg + 8, cb->prefix, cb->len) == 0) {
- cb->callback(sender, msg + 8);
+ if (strncmp(buffer + 8, cb->prefix, cb->len) == 0) {
+ cb->callback(sender, buffer + 8);
break;
}
spin_unlock(&smsg_list_lock);
}
- kfree(msg);
+ kfree(buffer);
}
-static iucv_interrupt_ops_t smsg_ops = {
- .ConnectionComplete = smsg_connection_complete,
- .MessagePending = smsg_message_pending,
-};
-
-static struct device_driver smsg_driver = {
- .name = "SMSGIUCV",
- .bus = &iucv_bus,
-};
-
-int
-smsg_register_callback(char *prefix, void (*callback)(char *from, char *str))
+int smsg_register_callback(char *prefix,
+ void (*callback)(char *from, char *str))
{
struct smsg_callback *cb;
@@ -110,18 +108,18 @@ smsg_register_callback(char *prefix, void (*callback)(char *from, char *str))
cb->prefix = prefix;
cb->len = strlen(prefix);
cb->callback = callback;
- spin_lock(&smsg_list_lock);
+ spin_lock_bh(&smsg_list_lock);
list_add_tail(&cb->list, &smsg_list);
- spin_unlock(&smsg_list_lock);
+ spin_unlock_bh(&smsg_list_lock);
return 0;
}
-void
-smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str))
+void smsg_unregister_callback(char *prefix,
+ void (*callback)(char *from, char *str))
{
struct smsg_callback *cb, *tmp;
- spin_lock(&smsg_list_lock);
+ spin_lock_bh(&smsg_list_lock);
cb = NULL;
list_for_each_entry(tmp, &smsg_list, list)
if (tmp->callback == callback &&
@@ -130,55 +128,58 @@ smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str))
list_del(&cb->list);
break;
}
- spin_unlock(&smsg_list_lock);
+ spin_unlock_bh(&smsg_list_lock);
kfree(cb);
}
-static void __exit
-smsg_exit(void)
+static struct device_driver smsg_driver = {
+ .name = "SMSGIUCV",
+ .bus = &iucv_bus,
+};
+
+static void __exit smsg_exit(void)
{
- if (smsg_handle > 0) {
- cpcmd("SET SMSG OFF", NULL, 0, NULL);
- iucv_sever(smsg_pathid, NULL);
- iucv_unregister_program(smsg_handle);
- driver_unregister(&smsg_driver);
- }
- return;
+ cpcmd("SET SMSG IUCV", NULL, 0, NULL);
+ iucv_unregister(&smsg_handler, 1);
+ driver_unregister(&smsg_driver);
}
-static int __init
-smsg_init(void)
+static int __init smsg_init(void)
{
- static unsigned char pgmmask[24] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
- };
int rc;
rc = driver_register(&smsg_driver);
- if (rc != 0) {
- printk(KERN_ERR "SMSGIUCV: failed to register driver.\n");
- return rc;
- }
- smsg_handle = iucv_register_program("SMSGIUCV ", "*MSG ",
- pgmmask, &smsg_ops, NULL);
- if (!smsg_handle) {
+ if (rc != 0)
+ goto out;
+ rc = iucv_register(&smsg_handler, 1);
+ if (rc) {
printk(KERN_ERR "SMSGIUCV: failed to register to iucv");
- driver_unregister(&smsg_driver);
- return -EIO; /* better errno ? */
+ rc = -EIO; /* better errno ? */
+ goto out_driver;
+ }
+ smsg_path = iucv_path_alloc(255, 0, GFP_KERNEL);
+ if (!smsg_path) {
+ rc = -ENOMEM;
+ goto out_register;
}
- rc = iucv_connect (&smsg_pathid, 255, NULL, "*MSG ", NULL, 0,
- NULL, NULL, smsg_handle, NULL);
+ rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG ",
+ NULL, NULL, NULL);
if (rc) {
printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG");
- iucv_unregister_program(smsg_handle);
- driver_unregister(&smsg_driver);
- smsg_handle = NULL;
- return -EIO;
+ rc = -EIO; /* better errno ? */
+ goto out_free;
}
cpcmd("SET SMSG IUCV", NULL, 0, NULL);
return 0;
+
+out_free:
+ iucv_path_free(smsg_path);
+out_register:
+ iucv_unregister(&smsg_handler, 1);
+out_driver:
+ driver_unregister(&smsg_driver);
+out:
+ return rc;
}
module_init(smsg_init);
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 437684084377..8f55e1431433 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1375,7 +1375,7 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
}
BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE);
- if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+ if (mtask->hdr->itt == RESERVED_ITT) {
struct iscsi_session *session = conn->session;
spin_lock_bh(&session->lock);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index d37048c96eab..7c75771c77ff 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -113,8 +113,7 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
hdr->opcode = ISCSI_OP_SCSI_CMD;
hdr->flags = ISCSI_ATTR_SIMPLE;
int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
- hdr->itt = ctask->itt | (conn->id << ISCSI_CID_SHIFT) |
- (session->age << ISCSI_AGE_SHIFT);
+ hdr->itt = build_itt(ctask->itt, conn->id, session->age);
hdr->data_length = cpu_to_be32(sc->request_bufflen);
hdr->cmdsn = cpu_to_be32(session->cmdsn);
session->cmdsn++;
@@ -270,7 +269,7 @@ invalid_datalen:
goto out;
}
- senselen = be16_to_cpu(*(uint16_t *)data);
+ senselen = be16_to_cpu(*(__be16 *)data);
if (datalen < senselen)
goto invalid_datalen;
@@ -338,7 +337,7 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) {
memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr));
- itt = rejected_pdu.itt & ISCSI_ITT_MASK;
+ itt = get_itt(rejected_pdu.itt);
printk(KERN_ERR "itt 0x%x had pdu (op 0x%x) rejected "
"due to DataDigest error.\n", itt,
rejected_pdu.opcode);
@@ -367,10 +366,10 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
struct iscsi_mgmt_task *mtask;
uint32_t itt;
- if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG))
- itt = hdr->itt & ISCSI_ITT_MASK;
+ if (hdr->itt != RESERVED_ITT)
+ itt = get_itt(hdr->itt);
else
- itt = hdr->itt;
+ itt = ~0U;
if (itt < session->cmds_max) {
ctask = session->cmds[itt];
@@ -440,7 +439,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
iscsi_tmf_rsp(conn, hdr);
break;
case ISCSI_OP_NOOP_IN:
- if (hdr->ttt != ISCSI_RESERVED_TAG || datalen) {
+ if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) {
rc = ISCSI_ERR_PROTO;
break;
}
@@ -457,7 +456,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
rc = ISCSI_ERR_BAD_OPCODE;
break;
}
- } else if (itt == ISCSI_RESERVED_TAG) {
+ } else if (itt == ~0U) {
rc = iscsi_check_assign_cmdsn(session,
(struct iscsi_nopin*)hdr);
if (rc)
@@ -470,7 +469,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
break;
}
- if (hdr->ttt == ISCSI_RESERVED_TAG)
+ if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG))
break;
if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0))
@@ -516,24 +515,24 @@ int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
struct iscsi_cmd_task *ctask;
uint32_t itt;
- if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
- if ((hdr->itt & ISCSI_AGE_MASK) !=
+ if (hdr->itt != RESERVED_ITT) {
+ if (((__force u32)hdr->itt & ISCSI_AGE_MASK) !=
(session->age << ISCSI_AGE_SHIFT)) {
printk(KERN_ERR "iscsi: received itt %x expected "
- "session age (%x)\n", hdr->itt,
+ "session age (%x)\n", (__force u32)hdr->itt,
session->age & ISCSI_AGE_MASK);
return ISCSI_ERR_BAD_ITT;
}
- if ((hdr->itt & ISCSI_CID_MASK) !=
+ if (((__force u32)hdr->itt & ISCSI_CID_MASK) !=
(conn->id << ISCSI_CID_SHIFT)) {
printk(KERN_ERR "iscsi: received itt %x, expected "
- "CID (%x)\n", hdr->itt, conn->id);
+ "CID (%x)\n", (__force u32)hdr->itt, conn->id);
return ISCSI_ERR_BAD_ITT;
}
- itt = hdr->itt & ISCSI_ITT_MASK;
+ itt = get_itt(hdr->itt);
} else
- itt = hdr->itt;
+ itt = ~0U;
if (itt < session->cmds_max) {
ctask = session->cmds[itt];
@@ -896,9 +895,8 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
/*
* pre-format CmdSN for outgoing PDU.
*/
- if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
- hdr->itt = mtask->itt | (conn->id << ISCSI_CID_SHIFT) |
- (session->age << ISCSI_AGE_SHIFT);
+ if (hdr->itt != RESERVED_ITT) {
+ hdr->itt = build_itt(mtask->itt, conn->id, session->age);
nop->cmdsn = cpu_to_be32(session->cmdsn);
if (conn->c_stage == ISCSI_CONN_STARTED &&
!(hdr->opcode & ISCSI_OP_IMMEDIATE))
@@ -1064,7 +1062,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
spin_lock_bh(&session->lock);
ctask->mtask = (struct iscsi_mgmt_task *)
- session->mgmt_cmds[(hdr->itt & ISCSI_ITT_MASK) -
+ session->mgmt_cmds[get_itt(hdr->itt) -
ISCSI_MGMT_ITT_OFFSET];
if (conn->tmabort_state == TMABORT_INITIAL) {
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 7d2311067903..bd6bbf61adb8 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -521,10 +521,10 @@ static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_
break;
default: ; /* probably FILL */
}
- aux->filemark_cnt = ntohl(STp->filemark_cnt);
- aux->phys_fm = ntohl(0xffffffff);
- aux->last_mark_ppos = ntohl(STp->last_mark_ppos);
- aux->last_mark_lbn = ntohl(STp->last_mark_lbn);
+ aux->filemark_cnt = htonl(STp->filemark_cnt);
+ aux->phys_fm = htonl(0xffffffff);
+ aux->last_mark_ppos = htonl(STp->last_mark_ppos);
+ aux->last_mark_lbn = htonl(STp->last_mark_lbn);
}
/*
diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h
index 1e426f5d0ed8..2cc7b5a1606a 100644
--- a/drivers/scsi/osst.h
+++ b/drivers/scsi/osst.h
@@ -288,11 +288,11 @@ typedef struct {
#else
#error "Please fix <asm/byteorder.h>"
#endif
- u16 max_speed; /* Maximum speed supported in KBps */
+ __be16 max_speed; /* Maximum speed supported in KBps */
u8 reserved10, reserved11;
- u16 ctl; /* Continuous Transfer Limit in blocks */
- u16 speed; /* Current Speed, in KBps */
- u16 buffer_size; /* Buffer Size, in 512 bytes */
+ __be16 ctl; /* Continuous Transfer Limit in blocks */
+ __be16 speed; /* Current Speed, in KBps */
+ __be16 buffer_size; /* Buffer Size, in 512 bytes */
u8 reserved18, reserved19;
} osst_capabilities_page_t;
@@ -352,8 +352,8 @@ typedef struct {
u8 reserved2;
u8 density;
u8 reserved3,reserved4;
- u16 segtrk;
- u16 trks;
+ __be16 segtrk;
+ __be16 trks;
u8 reserved5,reserved6,reserved7,reserved8,reserved9,reserved10;
} osst_tape_paramtr_page_t;
@@ -369,18 +369,18 @@ typedef struct {
typedef struct os_partition_s {
__u8 partition_num;
__u8 par_desc_ver;
- __u16 wrt_pass_cntr;
- __u32 first_frame_ppos;
- __u32 last_frame_ppos;
- __u32 eod_frame_ppos;
+ __be16 wrt_pass_cntr;
+ __be32 first_frame_ppos;
+ __be32 last_frame_ppos;
+ __be32 eod_frame_ppos;
} os_partition_t;
/*
* DAT entry
*/
typedef struct os_dat_entry_s {
- __u32 blk_sz;
- __u16 blk_cnt;
+ __be32 blk_sz;
+ __be16 blk_cnt;
__u8 flags;
__u8 reserved;
} os_dat_entry_t;
@@ -412,23 +412,23 @@ typedef struct os_dat_s {
* AUX
*/
typedef struct os_aux_s {
- __u32 format_id; /* hardware compability AUX is based on */
+ __be32 format_id; /* hardware compability AUX is based on */
char application_sig[4]; /* driver used to write this media */
- __u32 hdwr; /* reserved */
- __u32 update_frame_cntr; /* for configuration frame */
+ __be32 hdwr; /* reserved */
+ __be32 update_frame_cntr; /* for configuration frame */
__u8 frame_type;
__u8 frame_type_reserved;
__u8 reserved_18_19[2];
os_partition_t partition;
__u8 reserved_36_43[8];
- __u32 frame_seq_num;
- __u32 logical_blk_num_high;
- __u32 logical_blk_num;
+ __be32 frame_seq_num;
+ __be32 logical_blk_num_high;
+ __be32 logical_blk_num;
os_dat_t dat;
__u8 reserved188_191[4];
- __u32 filemark_cnt;
- __u32 phys_fm;
- __u32 last_mark_ppos;
+ __be32 filemark_cnt;
+ __be32 phys_fm;
+ __be32 last_mark_ppos;
__u8 reserved204_223[20];
/*
@@ -436,8 +436,8 @@ typedef struct os_aux_s {
*
* Linux specific fields:
*/
- __u32 next_mark_ppos; /* when known, points to next marker */
- __u32 last_mark_lbn; /* storing log_blk_num of last mark is extends ADR spec */
+ __be32 next_mark_ppos; /* when known, points to next marker */
+ __be32 last_mark_lbn; /* storing log_blk_num of last mark is extends ADR spec */
__u8 linux_specific[24];
__u8 reserved_256_511[256];
@@ -450,19 +450,19 @@ typedef struct os_fm_tab_s {
__u8 reserved_1;
__u8 fm_tab_ent_sz;
__u8 reserved_3;
- __u16 fm_tab_ent_cnt;
+ __be16 fm_tab_ent_cnt;
__u8 reserved6_15[10];
- __u32 fm_tab_ent[OS_FM_TAB_MAX];
+ __be32 fm_tab_ent[OS_FM_TAB_MAX];
} os_fm_tab_t;
typedef struct os_ext_trk_ey_s {
__u8 et_part_num;
__u8 fmt;
- __u16 fm_tab_off;
+ __be16 fm_tab_off;
__u8 reserved4_7[4];
- __u32 last_hlb_hi;
- __u32 last_hlb;
- __u32 last_pp;
+ __be32 last_hlb_hi;
+ __be32 last_hlb;
+ __be32 last_pp;
__u8 reserved20_31[12];
} os_ext_trk_ey_t;
@@ -479,17 +479,17 @@ typedef struct os_header_s {
char ident_str[8];
__u8 major_rev;
__u8 minor_rev;
- __u16 ext_trk_tb_off;
+ __be16 ext_trk_tb_off;
__u8 reserved12_15[4];
__u8 pt_par_num;
__u8 pt_reserved1_3[3];
os_partition_t partition[16];
- __u32 cfg_col_width;
- __u32 dat_col_width;
- __u32 qfa_col_width;
+ __be32 cfg_col_width;
+ __be32 dat_col_width;
+ __be32 qfa_col_width;
__u8 cartridge[16];
__u8 reserved304_511[208];
- __u32 old_filemark_list[16680/4]; /* in ADR 1.4 __u8 track_table[16680] */
+ __be32 old_filemark_list[16680/4]; /* in ADR 1.4 __u8 track_table[16680] */
os_ext_trk_tb_t ext_track_tb;
__u8 reserved17272_17735[464];
os_fm_tab_t dat_fm_tab;
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index db8607e3d531..f5051cf1a0c8 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -256,7 +256,7 @@ static void ulite_release_port(struct uart_port *port)
{
release_mem_region(port->mapbase, ULITE_REGION);
iounmap(port->membase);
- port->membase = 0;
+ port->membase = NULL;
}
static int ulite_request_port(struct uart_port *port)
@@ -438,7 +438,7 @@ static int __devinit ulite_probe(struct platform_device *pdev)
port->iotype = UPIO_MEM;
port->iobase = 1; /* mark port in use */
port->mapbase = res->start;
- port->membase = 0;
+ port->membase = NULL;
port->ops = &ulite_ops;
port->irq = res2->start;
port->flags = UPF_BOOT_AUTOCONF;
@@ -462,7 +462,7 @@ static int ulite_remove(struct platform_device *pdev)
uart_remove_one_port(&ulite_uart_driver, port);
/* mark port as free */
- port->membase = 0;
+ port->membase = NULL;
return 0;
}
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 371f194a9d39..4d781a2a9807 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -104,7 +104,7 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
__LINE__, dev->m_region->lpar_addr);
- result = ps3_alloc_io_irq(dev->interrupt_id, &virq);
+ result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
if (result) {
dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index ec0da0343be4..46fa57a520d0 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -677,10 +677,10 @@ static inline unsigned int ehci_readl (const struct ehci_hcd *ehci,
{
#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
return ehci_big_endian_mmio(ehci) ?
- readl_be((__force u32 *)regs) :
- readl((__force u32 *)regs);
+ readl_be(regs) :
+ readl(regs);
#else
- return readl((__force u32 *)regs);
+ return readl(regs);
#endif
}
@@ -689,10 +689,10 @@ static inline void ehci_writel (const struct ehci_hcd *ehci,
{
#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
ehci_big_endian_mmio(ehci) ?
- writel_be(val, (__force u32 *)regs) :
- writel(val, (__force u32 *)regs);
+ writel_be(val, regs) :
+ writel(val, regs);
#else
- writel(val, (__force u32 *)regs);
+ writel(val, regs);
#endif
}
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index 69d948b4a701..62283a3926de 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -107,7 +107,7 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
__LINE__, dev->m_region->lpar_addr);
- result = ps3_alloc_io_irq(dev->interrupt_id, &virq);
+ result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq);
if (result) {
dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n",
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 0dafcda37291..c2b5ecfe5e9f 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -507,10 +507,10 @@ static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci,
{
#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
return big_endian_mmio(ohci) ?
- readl_be ((__force u32 *)regs) :
- readl ((__force u32 *)regs);
+ readl_be (regs) :
+ readl (regs);
#else
- return readl ((__force u32 *)regs);
+ return readl (regs);
#endif
}
@@ -519,10 +519,10 @@ static inline void _ohci_writel (const struct ohci_hcd *ohci,
{
#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
big_endian_mmio(ohci) ?
- writel_be (val, (__force u32 *)regs) :
- writel (val, (__force u32 *)regs);
+ writel_be (val, regs) :
+ writel (val, regs);
#else
- writel (val, (__force u32 *)regs);
+ writel (val, regs);
#endif
}
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index a6f0f4d934df..31e5fe363fdc 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -70,12 +70,12 @@
(((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
struct gl_packet {
- u32 packet_length;
+ __le32 packet_length;
char packet_data [1];
};
struct gl_header {
- u32 packet_count;
+ __le32 packet_count;
struct gl_packet packets;
};
@@ -85,15 +85,14 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
struct gl_packet *packet;
struct sk_buff *gl_skb;
u32 size;
+ u32 count;
header = (struct gl_header *) skb->data;
// get the packet count of the received skb
- le32_to_cpus(&header->packet_count);
- if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
- || (header->packet_count < 0)) {
- dbg("genelink: invalid received packet count %d",
- header->packet_count);
+ count = le32_to_cpu(header->packet_count);
+ if (count > GL_MAX_TRANSMIT_PACKETS) {
+ dbg("genelink: invalid received packet count %u", count);
return 0;
}
@@ -103,7 +102,7 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
// decrement the length for the packet count size 4 bytes
skb_pull(skb, 4);
- while (header->packet_count > 1) {
+ while (count > 1) {
// get the packet length
size = le32_to_cpu(packet->packet_length);
@@ -124,9 +123,8 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
}
// advance to the next packet
- packet = (struct gl_packet *)
- &packet->packet_data [size];
- header->packet_count--;
+ packet = (struct gl_packet *)&packet->packet_data[size];
+ count--;
// shift the data pointer to the next gl_packet
skb_pull(skb, size + 4);
@@ -149,8 +147,8 @@ genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
int length = skb->len;
int headroom = skb_headroom(skb);
int tailroom = skb_tailroom(skb);
- u32 *packet_count;
- u32 *packet_len;
+ __le32 *packet_count;
+ __le32 *packet_len;
// FIXME: magic numbers, bleech
padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
@@ -172,7 +170,7 @@ genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
}
// attach the packet count to the header
- packet_count = (u32 *) skb_push(skb, (4 + 4*1));
+ packet_count = (__le32 *) skb_push(skb, (4 + 4*1));
packet_len = packet_count + 1;
*packet_count = cpu_to_le32(1);
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 06b4fffc189c..3ec24870bca9 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -170,13 +170,13 @@ static int cp2101_get_config(struct usb_serial_port* port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
- u32 *buf;
+ __le32 *buf;
int result, i, length;
/* Number of integers required to contain the array */
length = (((size - 1) | 3) + 1)/4;
- buf = kcalloc(length, sizeof(u32), GFP_KERNEL);
+ buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
if (!buf) {
dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
return -ENOMEM;
@@ -216,13 +216,13 @@ static int cp2101_set_config(struct usb_serial_port* port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
- u32 *buf;
+ __le32 *buf;
int result, i, length;
/* Number of integers required to contain the array */
length = (((size - 1) | 3) + 1)/4;
- buf = kmalloc(length * sizeof(u32), GFP_KERNEL);
+ buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
if (!buf) {
dev_err(&port->dev, "%s - out of memory.\n",
__FUNCTION__);