diff --git a/[refs] b/[refs] index 2cd005b6c16d..fd38cd90f800 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b892afd1e60132a981b963929e352eabf3306ba2 +refs/heads/master: 76f625511e61f9d5561885c77d2ff1436ed83797 diff --git a/trunk/Documentation/HOWTO b/trunk/Documentation/HOWTO index 48123dba5e6a..8d51c148f721 100644 --- a/trunk/Documentation/HOWTO +++ b/trunk/Documentation/HOWTO @@ -30,7 +30,6 @@ are not a good substitute for a solid C education and/or years of experience, the following books are good for, if anything, reference: - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall] - "Practical C Programming" by Steve Oualline [O'Reilly] - - "C: A Reference Manual" by Harbison and Steele [Prentice Hall] The kernel is written using GNU C and the GNU toolchain. While it adheres to the ISO C89 standard, it uses a number of extensions that are diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 2dc5e5da8f88..b3d1ce7e3ba0 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -333,10 +333,3 @@ Why: Unmaintained for years, superceded by JFFS2 for years. Who: Jeff Garzik --------------------------- - -What: sk98lin network driver -When: July 2007 -Why: In kernel tree version of driver is unmaintained. Sk98lin driver - replaced by the skge driver. -Who: Stephen Hemminger - diff --git a/trunk/Documentation/usb/proc_usb_info.txt b/trunk/Documentation/usb/proc_usb_info.txt index 077e9032d0cd..22c5331260ca 100644 --- a/trunk/Documentation/usb/proc_usb_info.txt +++ b/trunk/Documentation/usb/proc_usb_info.txt @@ -213,16 +213,15 @@ C:* #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA Interface descriptor info (can be multiple per Config): -I:* If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss -| | | | | | | | |__Driver name -| | | | | | | | or "(none)" -| | | | | | | |__InterfaceProtocol -| | | | | | |__InterfaceSubClass -| | | | | |__InterfaceClass -| | | | |__NumberOfEndpoints -| | | |__AlternateSettingNumber -| | |__InterfaceNumber -| |__ "*" indicates the active altsetting (others are " ") +I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss +| | | | | | | |__Driver name +| | | | | | | or "(none)" +| | | | | | |__InterfaceProtocol +| | | | | |__InterfaceSubClass +| | | | |__InterfaceClass +| | | |__NumberOfEndpoints +| | |__AlternateSettingNumber +| |__InterfaceNumber |__Interface info tag A given interface may have one or more "alternate" settings. @@ -278,7 +277,7 @@ of the USB devices on a system's root hub. (See more below on how to do this.) The Interface lines can be used to determine what driver is -being used for each device, and which altsetting it activated. +being used for each device. The Configuration lines could be used to list maximum power (in milliamps) that a system's USB devices are using. diff --git a/trunk/Documentation/usb/usbmon.txt b/trunk/Documentation/usb/usbmon.txt index 0f6808abd612..e65ec828d7aa 100644 --- a/trunk/Documentation/usb/usbmon.txt +++ b/trunk/Documentation/usb/usbmon.txt @@ -77,7 +77,7 @@ that the file size is not excessive for your favourite editor. The '1t' type data consists of a stream of events, such as URB submission, URB callback, submission error. Every event is a text line, which consists -of whitespace separated words. The number or position of words may depend +of whitespace separated words. The number of position of words may depend on the event type, but there is a set of words, common for all types. Here is the list of words, from left to right: @@ -170,152 +170,4 @@ dd65f0e8 4128379808 C Bo:005:02 0 31 > * Raw binary format and API -The overall architecture of the API is about the same as the one above, -only the events are delivered in binary format. Each event is sent in -the following structure (its name is made up, so that we can refer to it): - -struct usbmon_packet { - u64 id; /* 0: URB ID - from submission to callback */ - unsigned char type; /* 8: Same as text; extensible. */ - unsigned char xfer_type; /* ISO (0), Intr, Control, Bulk (3) */ - unsigned char epnum; /* Endpoint number and transfer direction */ - unsigned char devnum; /* Device address */ - u16 busnum; /* 12: Bus number */ - char flag_setup; /* 14: Same as text */ - char flag_data; /* 15: Same as text; Binary zero is OK. */ - s64 ts_sec; /* 16: gettimeofday */ - s32 ts_usec; /* 24: gettimeofday */ - int status; /* 28: */ - unsigned int length; /* 32: Length of data (submitted or actual) */ - unsigned int len_cap; /* 36: Delivered length */ - unsigned char setup[8]; /* 40: Only for Control 'S' */ -}; /* 48 bytes total */ - -These events can be received from a character device by reading with read(2), -with an ioctl(2), or by accessing the buffer with mmap. - -The character device is usually called /dev/usbmonN, where N is the USB bus -number. Number zero (/dev/usbmon0) is special and means "all buses". -However, this feature is not implemented yet. Note that specific naming -policy is set by your Linux distribution. - -If you create /dev/usbmon0 by hand, make sure that it is owned by root -and has mode 0600. Otherwise, unpriviledged users will be able to snoop -keyboard traffic. - -The following ioctl calls are available, with MON_IOC_MAGIC 0x92: - - MON_IOCQ_URB_LEN, defined as _IO(MON_IOC_MAGIC, 1) - -This call returns the length of data in the next event. Note that majority of -events contain no data, so if this call returns zero, it does not mean that -no events are available. - - MON_IOCG_STATS, defined as _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats) - -The argument is a pointer to the following structure: - -struct mon_bin_stats { - u32 queued; - u32 dropped; -}; - -The member "queued" refers to the number of events currently queued in the -buffer (and not to the number of events processed since the last reset). - -The member "dropped" is the number of events lost since the last call -to MON_IOCG_STATS. - - MON_IOCT_RING_SIZE, defined as _IO(MON_IOC_MAGIC, 4) - -This call sets the buffer size. The argument is the size in bytes. -The size may be rounded down to the next chunk (or page). If the requested -size is out of [unspecified] bounds for this kernel, the call fails with --EINVAL. - - MON_IOCQ_RING_SIZE, defined as _IO(MON_IOC_MAGIC, 5) - -This call returns the current size of the buffer in bytes. - - MON_IOCX_GET, defined as _IOW(MON_IOC_MAGIC, 6, struct mon_get_arg) - -This call waits for events to arrive if none were in the kernel buffer, -then returns the first event. Its argument is a pointer to the following -structure: - -struct mon_get_arg { - struct usbmon_packet *hdr; - void *data; - size_t alloc; /* Length of data (can be zero) */ -}; - -Before the call, hdr, data, and alloc should be filled. Upon return, the area -pointed by hdr contains the next event structure, and the data buffer contains -the data, if any. The event is removed from the kernel buffer. - - MON_IOCX_MFETCH, defined as _IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg) - -This ioctl is primarily used when the application accesses the buffer -with mmap(2). Its argument is a pointer to the following structure: - -struct mon_mfetch_arg { - uint32_t *offvec; /* Vector of events fetched */ - uint32_t nfetch; /* Number of events to fetch (out: fetched) */ - uint32_t nflush; /* Number of events to flush */ -}; - -The ioctl operates in 3 stages. - -First, it removes and discards up to nflush events from the kernel buffer. -The actual number of events discarded is returned in nflush. - -Second, it waits for an event to be present in the buffer, unless the pseudo- -device is open with O_NONBLOCK. - -Third, it extracts up to nfetch offsets into the mmap buffer, and stores -them into the offvec. The actual number of event offsets is stored into -the nfetch. - - MON_IOCH_MFLUSH, defined as _IO(MON_IOC_MAGIC, 8) - -This call removes a number of events from the kernel buffer. Its argument -is the number of events to remove. If the buffer contains fewer events -than requested, all events present are removed, and no error is reported. -This works when no events are available too. - - FIONBIO - -The ioctl FIONBIO may be implemented in the future, if there's a need. - -In addition to ioctl(2) and read(2), the special file of binary API can -be polled with select(2) and poll(2). But lseek(2) does not work. - -* Memory-mapped access of the kernel buffer for the binary API - -The basic idea is simple: - -To prepare, map the buffer by getting the current size, then using mmap(2). -Then, execute a loop similar to the one written in pseudo-code below: - - struct mon_mfetch_arg fetch; - struct usbmon_packet *hdr; - int nflush = 0; - for (;;) { - fetch.offvec = vec; // Has N 32-bit words - fetch.nfetch = N; // Or less than N - fetch.nflush = nflush; - ioctl(fd, MON_IOCX_MFETCH, &fetch); // Process errors, too - nflush = fetch.nfetch; // This many packets to flush when done - for (i = 0; i < nflush; i++) { - hdr = (struct ubsmon_packet *) &mmap_area[vec[i]]; - if (hdr->type == '@') // Filler packet - continue; - caddr_t data = &mmap_area[vec[i]] + 64; - process_packet(hdr, data); - } - } - -Thus, the main idea is to execute only one ioctl per N events. - -Although the buffer is circular, the returned headers and data do not cross -the end of the buffer, so the above pseudo-code does not need any gathering. +TBD diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index fe35f3ac4cd3..96135d285eb0 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -598,16 +598,6 @@ M: ecashin@coraid.com W: http://www.coraid.com/support/linux S: Supported -ATL1 ETHERNET DRIVER -P: Jay Cliburn -M: jcliburn@gmail.com -P: Chris Snook -M: csnook@redhat.com -L: atl1-devel@lists.sourceforge.net -W: http://sourceforge.net/projects/atl1 -W: http://atl1.sourceforge.net -S: Maintained - ATM P: Chas Williams M: chas@cmf.nrl.navy.mil @@ -2495,12 +2485,6 @@ L: orinoco-devel@lists.sourceforge.net W: http://www.nongnu.org/orinoco/ S: Maintained -PA SEMI ETHERNET DRIVER -P: Olof Johansson -M: olof@lixom.net -L: netdev@vger.kernel.org -S: Maintained - PARALLEL PORT SUPPORT P: Phil Blundell M: philb@gnu.org @@ -2670,7 +2654,7 @@ S: Supported PRISM54 WIRELESS DRIVER P: Prism54 Development Team -M: developers@islsm.org +M: prism54-private@prism54.org L: netdev@vger.kernel.org W: http://prism54.org S: Maintained diff --git a/trunk/arch/alpha/kernel/pci.c b/trunk/arch/alpha/kernel/pci.c index ab642a4f08de..3c10b9a1ddf5 100644 --- a/trunk/arch/alpha/kernel/pci.c +++ b/trunk/arch/alpha/kernel/pci.c @@ -575,7 +575,3 @@ void pci_iounmap(struct pci_dev *dev, void __iomem * addr) EXPORT_SYMBOL(pci_iomap); EXPORT_SYMBOL(pci_iounmap); - -/* FIXME: Some boxes have multiple ISA bridges! */ -struct pci_dev *isa_bridge; -EXPORT_SYMBOL(isa_bridge); diff --git a/trunk/arch/i386/kernel/io_apic.c b/trunk/arch/i386/kernel/io_apic.c index 5592fa6e1fa1..6a3875f81a0a 100644 --- a/trunk/arch/i386/kernel/io_apic.c +++ b/trunk/arch/i386/kernel/io_apic.c @@ -2606,32 +2606,25 @@ static struct irq_chip msi_chip = { .retrigger = ioapic_retrigger_irq, }; -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev) { struct msi_msg msg; - int irq, ret; - irq = create_irq(); - if (irq < 0) - return irq; - - set_irq_msi(irq, desc); + int ret; ret = msi_compose_msg(dev, irq, &msg); - if (ret < 0) { - destroy_irq(irq); + if (ret < 0) return ret; - } write_msi_msg(irq, &msg); set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); - return irq; + return 0; } void arch_teardown_msi_irq(unsigned int irq) { - destroy_irq(irq); + return; } #endif /* CONFIG_PCI_MSI */ diff --git a/trunk/arch/ia64/kernel/msi_ia64.c b/trunk/arch/ia64/kernel/msi_ia64.c index 0d05450c91c4..822e59a1b822 100644 --- a/trunk/arch/ia64/kernel/msi_ia64.c +++ b/trunk/arch/ia64/kernel/msi_ia64.c @@ -64,17 +64,12 @@ static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) } #endif /* CONFIG_SMP */ -int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) +int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) { struct msi_msg msg; unsigned long dest_phys_id; - unsigned int irq, vector; + unsigned int vector; - irq = create_irq(); - if (irq < 0) - return irq; - - set_irq_msi(irq, desc); dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); vector = irq; @@ -94,12 +89,12 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) write_msi_msg(irq, &msg); set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); - return irq; + return 0; } void ia64_teardown_msi_irq(unsigned int irq) { - destroy_irq(irq); + return; /* no-op */ } static void ia64_ack_msi_irq(unsigned int irq) @@ -131,12 +126,12 @@ static struct irq_chip ia64_msi_chip = { }; -int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) +int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) { if (platform_setup_msi_irq) - return platform_setup_msi_irq(pdev, desc); + return platform_setup_msi_irq(irq, pdev); - return ia64_setup_msi_irq(pdev, desc); + return ia64_setup_msi_irq(irq, pdev); } void arch_teardown_msi_irq(unsigned int irq) diff --git a/trunk/arch/ia64/sn/kernel/msi_sn.c b/trunk/arch/ia64/sn/kernel/msi_sn.c index ea3dc38d73fd..b3a435fd70fb 100644 --- a/trunk/arch/ia64/sn/kernel/msi_sn.c +++ b/trunk/arch/ia64/sn/kernel/msi_sn.c @@ -59,12 +59,13 @@ void sn_teardown_msi_irq(unsigned int irq) sn_intr_free(nasid, widget, sn_irq_info); sn_msi_info[irq].sn_irq_info = NULL; - destroy_irq(irq); + return; } -int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) +int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) { struct msi_msg msg; + struct msi_desc *entry; int widget; int status; nasid_t nasid; @@ -72,8 +73,8 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) struct sn_irq_info *sn_irq_info; struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); - int irq; + entry = get_irq_data(irq); if (!entry->msi_attrib.is_64) return -EINVAL; @@ -83,11 +84,6 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) if (provider == NULL || provider->dma_map_consistent == NULL) return -EINVAL; - irq = create_irq(); - if (irq < 0) - return irq; - - set_irq_msi(irq, entry); /* * Set up the vector plumbing. Let the prom (via sn_intr_alloc) * decide which cpu to direct this msi at by default. @@ -99,15 +95,12 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) SWIN_WIDGETNUM(bussoft->bs_base); sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); - if (! sn_irq_info) { - destroy_irq(irq); + if (! sn_irq_info) return -ENOMEM; - } status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1); if (status) { kfree(sn_irq_info); - destroy_irq(irq); return -ENOMEM; } @@ -128,7 +121,6 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) if (! bus_addr) { sn_intr_free(nasid, widget, sn_irq_info); kfree(sn_irq_info); - destroy_irq(irq); return -ENOMEM; } @@ -147,7 +139,7 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) write_msi_msg(irq, &msg); set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); - return irq; + return 0; } #ifdef CONFIG_SMP diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index c1e01b22addc..d6abe495c6b0 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -529,11 +529,6 @@ config PPC_PS3 bool "Sony PS3 (incomplete)" depends on PPC_MULTIPLATFORM && PPC64 select PPC_CELL - select USB_ARCH_HAS_OHCI - select USB_OHCI_LITTLE_ENDIAN - select USB_OHCI_BIG_ENDIAN_MMIO - select USB_ARCH_HAS_EHCI - select USB_EHCI_BIG_ENDIAN_MMIO help This option enables support for the Sony PS3 game console and other platforms using the PS3 hypervisor. diff --git a/trunk/arch/powerpc/kernel/pci_64.c b/trunk/arch/powerpc/kernel/pci_64.c index 2b52b087aaa8..01f18c683407 100644 --- a/trunk/arch/powerpc/kernel/pci_64.c +++ b/trunk/arch/powerpc/kernel/pci_64.c @@ -381,6 +381,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, pci_device_add(dev, bus); + /* XXX pci_scan_msi_device(dev); */ + return dev; } EXPORT_SYMBOL(of_create_pci_dev); diff --git a/trunk/arch/x86_64/kernel/io_apic.c b/trunk/arch/x86_64/kernel/io_apic.c index 6be6730acb5c..d7bad90a5ad8 100644 --- a/trunk/arch/x86_64/kernel/io_apic.c +++ b/trunk/arch/x86_64/kernel/io_apic.c @@ -1956,31 +1956,24 @@ static struct irq_chip msi_chip = { .retrigger = ioapic_retrigger_irq, }; -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev) { struct msi_msg msg; - int irq, ret; - irq = create_irq(); - if (irq < 0) - return irq; - - set_irq_msi(irq, desc); + int ret; ret = msi_compose_msg(dev, irq, &msg); - if (ret < 0) { - destroy_irq(irq); + if (ret < 0) return ret; - } write_msi_msg(irq, &msg); set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); - return irq; + return 0; } void arch_teardown_msi_irq(unsigned int irq) { - destroy_irq(irq); + return; } #endif /* CONFIG_PCI_MSI */ diff --git a/trunk/drivers/base/class.c b/trunk/drivers/base/class.c index 96def1ddba19..8bf2ca2e56b5 100644 --- a/trunk/drivers/base/class.c +++ b/trunk/drivers/base/class.c @@ -364,7 +364,7 @@ char *make_class_name(const char *name, struct kobject *kobj) class_name = kmalloc(size, GFP_KERNEL); if (!class_name) - return NULL; + return ERR_PTR(-ENOMEM); strcpy(class_name, name); strcat(class_name, ":"); @@ -411,11 +411,8 @@ static int make_deprecated_class_device_links(struct class_device *class_dev) return 0; class_name = make_class_name(class_dev->class->name, &class_dev->kobj); - if (class_name) - error = sysfs_create_link(&class_dev->dev->kobj, - &class_dev->kobj, class_name); - else - error = -ENOMEM; + error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, + class_name); kfree(class_name); return error; } @@ -428,8 +425,7 @@ static void remove_deprecated_class_device_links(struct class_device *class_dev) return; class_name = make_class_name(class_dev->class->name, &class_dev->kobj); - if (class_name) - sysfs_remove_link(&class_dev->dev->kobj, class_name); + sysfs_remove_link(&class_dev->dev->kobj, class_name); kfree(class_name); } #else @@ -867,12 +863,9 @@ int class_device_rename(struct class_device *class_dev, char *new_name) if (class_dev->dev) { new_class_name = make_class_name(class_dev->class->name, &class_dev->kobj); - if (new_class_name) - sysfs_create_link(&class_dev->dev->kobj, - &class_dev->kobj, new_class_name); - if (old_class_name) - sysfs_remove_link(&class_dev->dev->kobj, - old_class_name); + sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, + new_class_name); + sysfs_remove_link(&class_dev->dev->kobj, old_class_name); } #endif class_device_put(class_dev); diff --git a/trunk/drivers/base/core.c b/trunk/drivers/base/core.c index e13614241c9e..67b79a7592a9 100644 --- a/trunk/drivers/base/core.c +++ b/trunk/drivers/base/core.c @@ -95,8 +95,6 @@ static void device_release(struct kobject * kobj) if (dev->release) dev->release(dev); - else if (dev->type && dev->type->release) - dev->type->release(dev); else if (dev->class && dev->class->dev_release) dev->class->dev_release(dev); else { @@ -156,47 +154,25 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, "MINOR=%u", MINOR(dev->devt)); } - if (dev->driver) +#ifdef CONFIG_SYSFS_DEPRECATED + /* add bus name (same as SUBSYSTEM, deprecated) */ + if (dev->bus) add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "DRIVER=%s", dev->driver->name); + "PHYSDEVBUS=%s", dev->bus->name); +#endif + /* add driver name (PHYSDEV* values are deprecated)*/ + if (dev->driver) { + add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "DRIVER=%s", dev->driver->name); #ifdef CONFIG_SYSFS_DEPRECATED - if (dev->class) { - struct device *parent = dev->parent; - - /* find first bus device in parent chain */ - while (parent && !parent->bus) - parent = parent->parent; - if (parent && parent->bus) { - const char *path; - - path = kobject_get_path(&parent->kobj, GFP_KERNEL); - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVPATH=%s", path); - kfree(path); - - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", parent->bus->name); - - if (parent->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", parent->driver->name); - } - } else if (dev->bus) { add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "PHYSDEVBUS=%s", dev->bus->name); - - if (dev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", dev->driver->name); - } + "PHYSDEVDRIVER=%s", dev->driver->name); #endif + } /* terminate, set to next free slot, shrink available space */ envp[i] = NULL; @@ -208,25 +184,19 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, if (dev->bus && dev->bus->uevent) { /* have the bus specific function add its stuff */ retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size); - if (retval) - pr_debug ("%s: bus uevent() returned %d\n", + if (retval) { + pr_debug ("%s - uevent() returned %d\n", __FUNCTION__, retval); + } } if (dev->class && dev->class->dev_uevent) { /* have the class specific function add its stuff */ retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size); - if (retval) - pr_debug("%s: class uevent() returned %d\n", - __FUNCTION__, retval); - } - - if (dev->type && dev->type->uevent) { - /* have the device type specific fuction add its stuff */ - retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size); - if (retval) - pr_debug("%s: dev_type uevent() returned %d\n", - __FUNCTION__, retval); + if (retval) { + pr_debug("%s - dev_uevent() returned %d\n", + __FUNCTION__, retval); + } } return retval; @@ -277,50 +247,37 @@ static void device_remove_groups(struct device *dev) static int device_add_attrs(struct device *dev) { struct class *class = dev->class; - struct device_type *type = dev->type; int error = 0; int i; - if (class && class->dev_attrs) { + if (!class) + return 0; + + if (class->dev_attrs) { for (i = 0; attr_name(class->dev_attrs[i]); i++) { error = device_create_file(dev, &class->dev_attrs[i]); if (error) break; } - if (error) - while (--i >= 0) - device_remove_file(dev, &class->dev_attrs[i]); } - - if (type && type->attrs) { - for (i = 0; attr_name(type->attrs[i]); i++) { - error = device_create_file(dev, &type->attrs[i]); - if (error) - break; - } - if (error) - while (--i >= 0) - device_remove_file(dev, &type->attrs[i]); - } - + if (error) + while (--i >= 0) + device_remove_file(dev, &class->dev_attrs[i]); return error; } static void device_remove_attrs(struct device *dev) { struct class *class = dev->class; - struct device_type *type = dev->type; int i; - if (class && class->dev_attrs) { + if (!class) + return; + + if (class->dev_attrs) { for (i = 0; attr_name(class->dev_attrs[i]); i++) device_remove_file(dev, &class->dev_attrs[i]); } - - if (type && type->attrs) { - for (i = 0; attr_name(type->attrs[i]); i++) - device_remove_file(dev, &type->attrs[i]); - } } @@ -433,23 +390,22 @@ void device_initialize(struct device *dev) } #ifdef CONFIG_SYSFS_DEPRECATED -static struct kobject * get_device_parent(struct device *dev, - struct device *parent) +static int setup_parent(struct device *dev, struct device *parent) { /* Set the parent to the class, not the parent device */ /* this keeps sysfs from having a symlink to make old udevs happy */ if (dev->class) - return &dev->class->subsys.kset.kobj; + dev->kobj.parent = &dev->class->subsys.kset.kobj; else if (parent) - return &parent->kobj; + dev->kobj.parent = &parent->kobj; - return NULL; + return 0; } #else -static struct kobject * virtual_device_parent(struct device *dev) +static int virtual_device_parent(struct device *dev) { if (!dev->class) - return ERR_PTR(-ENODEV); + return -ENODEV; if (!dev->class->virtual_dir) { static struct kobject *virtual_dir = NULL; @@ -459,31 +415,25 @@ static struct kobject * virtual_device_parent(struct device *dev) dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); } - return dev->class->virtual_dir; + dev->kobj.parent = dev->class->virtual_dir; + return 0; } -static struct kobject * get_device_parent(struct device *dev, - struct device *parent) +static int setup_parent(struct device *dev, struct device *parent) { + int error; + /* if this is a class device, and has no parent, create one */ if ((dev->class) && (parent == NULL)) { - return virtual_device_parent(dev); + error = virtual_device_parent(dev); + if (error) + return error; } else if (parent) - return &parent->kobj; - return NULL; -} + dev->kobj.parent = &parent->kobj; -#endif -static int setup_parent(struct device *dev, struct device *parent) -{ - struct kobject *kobj; - kobj = get_device_parent(dev, parent); - if (IS_ERR(kobj)) - return PTR_ERR(kobj); - if (kobj) - dev->kobj.parent = kobj; return 0; } +#endif /** * device_add - add device to device hierarchy. @@ -570,13 +520,9 @@ int device_add(struct device *dev) &dev->kobj, dev->bus_id); #ifdef CONFIG_SYSFS_DEPRECATED if (parent) { - sysfs_create_link(&dev->kobj, &dev->parent->kobj, - "device"); - class_name = make_class_name(dev->class->name, - &dev->kobj); - if (class_name) - sysfs_create_link(&dev->parent->kobj, - &dev->kobj, class_name); + sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); + class_name = make_class_name(dev->class->name, &dev->kobj); + sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); } #endif } @@ -589,8 +535,7 @@ int device_add(struct device *dev) goto PMError; if ((error = bus_add_device(dev))) goto BusError; - if (!dev->uevent_suppress) - kobject_uevent(&dev->kobj, KOBJ_ADD); + kobject_uevent(&dev->kobj, KOBJ_ADD); if ((error = bus_attach_device(dev))) goto AttachError; if (parent) @@ -720,9 +665,7 @@ void device_del(struct device * dev) if (parent) { char *class_name = make_class_name(dev->class->name, &dev->kobj); - if (class_name) - sysfs_remove_link(&dev->parent->kobj, - class_name); + sysfs_remove_link(&dev->parent->kobj, class_name); kfree(class_name); sysfs_remove_link(&dev->kobj, "device"); } @@ -1025,25 +968,20 @@ static int device_move_class_links(struct device *dev, class_name = make_class_name(dev->class->name, &dev->kobj); if (!class_name) { - error = -ENOMEM; + error = PTR_ERR(class_name); + class_name = NULL; goto out; } if (old_parent) { sysfs_remove_link(&dev->kobj, "device"); sysfs_remove_link(&old_parent->kobj, class_name); } - if (new_parent) { - error = sysfs_create_link(&dev->kobj, &new_parent->kobj, - "device"); - if (error) - goto out; - error = sysfs_create_link(&new_parent->kobj, &dev->kobj, - class_name); - if (error) - sysfs_remove_link(&dev->kobj, "device"); - } - else - error = 0; + error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device"); + if (error) + goto out; + error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name); + if (error) + sysfs_remove_link(&dev->kobj, "device"); out: kfree(class_name); return error; @@ -1055,28 +993,29 @@ static int device_move_class_links(struct device *dev, /** * device_move - moves a device to a new parent * @dev: the pointer to the struct device to be moved - * @new_parent: the new parent of the device (can by NULL) + * @new_parent: the new parent of the device */ int device_move(struct device *dev, struct device *new_parent) { int error; struct device *old_parent; - struct kobject *new_parent_kobj; dev = get_device(dev); if (!dev) return -EINVAL; + if (!device_is_registered(dev)) { + error = -EINVAL; + goto out; + } new_parent = get_device(new_parent); - new_parent_kobj = get_device_parent (dev, new_parent); - if (IS_ERR(new_parent_kobj)) { - error = PTR_ERR(new_parent_kobj); - put_device(new_parent); + if (!new_parent) { + error = -EINVAL; goto out; } pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id, - new_parent ? new_parent->bus_id : ""); - error = kobject_move(&dev->kobj, new_parent_kobj); + new_parent->bus_id); + error = kobject_move(&dev->kobj, &new_parent->kobj); if (error) { put_device(new_parent); goto out; @@ -1085,8 +1024,7 @@ int device_move(struct device *dev, struct device *new_parent) dev->parent = new_parent; if (old_parent) klist_remove(&dev->knode_parent); - if (new_parent) - klist_add_tail(&dev->knode_parent, &new_parent->klist_children); + klist_add_tail(&dev->knode_parent, &new_parent->klist_children); if (!dev->class) goto out_put; error = device_move_class_links(dev, old_parent, new_parent); @@ -1094,8 +1032,7 @@ int device_move(struct device *dev, struct device *new_parent) /* We ignore errors on cleanup since we're hosed anyway... */ device_move_class_links(dev, new_parent, old_parent); if (!kobject_move(&dev->kobj, &old_parent->kobj)) { - if (new_parent) - klist_remove(&dev->knode_parent); + klist_remove(&dev->knode_parent); if (old_parent) klist_add_tail(&dev->knode_parent, &old_parent->klist_children); diff --git a/trunk/drivers/base/dd.c b/trunk/drivers/base/dd.c index b5bf243d9cd6..510e7884975f 100644 --- a/trunk/drivers/base/dd.c +++ b/trunk/drivers/base/dd.c @@ -86,12 +86,8 @@ static void driver_sysfs_remove(struct device *dev) */ int device_bind_driver(struct device *dev) { - int ret; - - ret = driver_sysfs_add(dev); - if (!ret) - driver_bound(dev); - return ret; + driver_bound(dev); + return driver_sysfs_add(dev); } struct stupid_thread_structure { @@ -140,17 +136,18 @@ static int really_probe(void *void_data) driver_sysfs_remove(dev); dev->driver = NULL; - if (ret != -ENODEV && ret != -ENXIO) { + if (ret == -ENODEV || ret == -ENXIO) { + /* Driver matched, but didn't support device + * or device not found. + * Not an error; keep going. + */ + ret = 0; + } else { /* driver matched but the probe failed */ printk(KERN_WARNING "%s: probe of %s failed with error %d\n", drv->name, dev->bus_id, ret); } - /* - * Ignore errors returned by ->probe so that the next driver can try - * its luck. - */ - ret = 0; done: kfree(data); atomic_dec(&probe_count); diff --git a/trunk/drivers/base/firmware_class.c b/trunk/drivers/base/firmware_class.c index c0a979a5074b..64558f45e6bc 100644 --- a/trunk/drivers/base/firmware_class.c +++ b/trunk/drivers/base/firmware_class.c @@ -35,7 +35,7 @@ enum { FW_STATUS_READY_NOHOTPLUG, }; -static int loading_timeout = 60; /* In seconds */ +static int loading_timeout = 10; /* In seconds */ /* fw_lock could be moved to 'struct firmware_priv' but since it is just * guarding for corner cases a global lock should be OK */ diff --git a/trunk/drivers/base/platform.c b/trunk/drivers/base/platform.c index 30480f6f2af2..f9c903ba9fcd 100644 --- a/trunk/drivers/base/platform.c +++ b/trunk/drivers/base/platform.c @@ -611,15 +611,8 @@ EXPORT_SYMBOL_GPL(platform_bus_type); int __init platform_bus_init(void) { - int error; - - error = device_register(&platform_bus); - if (error) - return error; - error = bus_register(&platform_bus_type); - if (error) - device_unregister(&platform_bus); - return error; + device_register(&platform_bus); + return bus_register(&platform_bus_type); } #ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK diff --git a/trunk/drivers/char/drm/via_dma.c b/trunk/drivers/char/drm/via_dma.c index a691ae74129d..2f72cbefc2ff 100644 --- a/trunk/drivers/char/drm/via_dma.c +++ b/trunk/drivers/char/drm/via_dma.c @@ -480,6 +480,7 @@ static int via_hook_segment(drm_via_private_t * dev_priv, VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); + VIA_READ(VIA_REG_TRANSPACE); } } return paused; @@ -557,8 +558,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); - + DRM_WRITEMEMORYBARRIER(); VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); + VIA_READ(VIA_REG_TRANSPACE); } static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) diff --git a/trunk/drivers/char/drm/via_dmablit.c b/trunk/drivers/char/drm/via_dmablit.c index 806f9ce5f47b..2054d5773717 100644 --- a/trunk/drivers/char/drm/via_dmablit.c +++ b/trunk/drivers/char/drm/via_dmablit.c @@ -218,7 +218,9 @@ via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine) VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); + DRM_WRITEMEMORYBARRIER(); VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); + VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04); } /* diff --git a/trunk/drivers/i2c/chips/isp1301_omap.c b/trunk/drivers/i2c/chips/isp1301_omap.c index 9fafadb92510..ccdf3e90862b 100644 --- a/trunk/drivers/i2c/chips/isp1301_omap.c +++ b/trunk/drivers/i2c/chips/isp1301_omap.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig index ec03341d2bd8..3f828052f8d2 100644 --- a/trunk/drivers/ide/Kconfig +++ b/trunk/drivers/ide/Kconfig @@ -167,13 +167,6 @@ config BLK_DEV_IDECS Support for Compact Flash cards, outboard IDE disks, tape drives, and CD-ROM drives connected through a PCMCIA card. -config BLK_DEV_DELKIN - tristate "Cardbus IDE support (Delkin/ASKA/Workbit)" - depends on CARDBUS && PCI - help - Support for Delkin, ASKA, and Workbit Cardbus CompactFlash - Adapters. This may also work for similar SD and XD adapters. - config BLK_DEV_IDECD tristate "Include IDE/ATAPI CDROM support" ---help--- @@ -271,13 +264,6 @@ config BLK_DEV_IDESCSI If both this SCSI emulation and native ATAPI support are compiled into the kernel, the native support will be used. -config BLK_DEV_IDEACPI - bool "IDE ACPI support" - depends on ACPI - ---help--- - Implement ACPI support for generic IDE devices. On modern - machines ACPI support is required to properly handle ACPI S3 states. - config IDE_TASK_IOCTL bool "IDE Taskfile Access" help @@ -620,11 +606,6 @@ config BLK_DEV_PIIX the kernel to change PIO, DMA and UDMA speeds and to configure the chip to optimum performance. -config BLK_DEV_IT8213 - tristate "IT8213 IDE support" - help - This driver adds support for the ITE 8213 IDE controller. - config BLK_DEV_IT821X tristate "IT821X IDE support" help @@ -761,11 +742,6 @@ config BLK_DEV_VIA82CXXX This allows the kernel to change PIO, DMA and UDMA speeds and to configure the chip to optimum performance. -config BLK_DEV_TC86C001 - tristate "Toshiba TC86C001 support" - help - This driver adds support for Toshiba TC86C001 GOKU-S chip. - endif config BLK_DEV_IDE_PMAC diff --git a/trunk/drivers/ide/Makefile b/trunk/drivers/ide/Makefile index d9f029e8ff74..569fae717503 100644 --- a/trunk/drivers/ide/Makefile +++ b/trunk/drivers/ide/Makefile @@ -22,7 +22,6 @@ ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o ide-core-$(CONFIG_PROC_FS) += ide-proc.o ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o -ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o # built-in only drivers from arm/ ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o diff --git a/trunk/drivers/ide/ide-acpi.c b/trunk/drivers/ide/ide-acpi.c deleted file mode 100644 index 17aea65d7dd2..000000000000 --- a/trunk/drivers/ide/ide-acpi.c +++ /dev/null @@ -1,697 +0,0 @@ -/* - * ide-acpi.c - * Provides ACPI support for IDE drives. - * - * Copyright (C) 2005 Intel Corp. - * Copyright (C) 2005 Randy Dunlap - * Copyright (C) 2006 SUSE Linux Products GmbH - * Copyright (C) 2006 Hannes Reinecke - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define REGS_PER_GTF 7 -struct taskfile_array { - u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ -}; - -struct GTM_buffer { - u32 PIO_speed0; - u32 DMA_speed0; - u32 PIO_speed1; - u32 DMA_speed1; - u32 GTM_flags; -}; - -struct ide_acpi_drive_link { - ide_drive_t *drive; - acpi_handle obj_handle; - u8 idbuff[512]; -}; - -struct ide_acpi_hwif_link { - ide_hwif_t *hwif; - acpi_handle obj_handle; - struct GTM_buffer gtm; - struct ide_acpi_drive_link master; - struct ide_acpi_drive_link slave; -}; - -#undef DEBUGGING -/* note: adds function name and KERN_DEBUG */ -#ifdef DEBUGGING -#define DEBPRINT(fmt, args...) \ - printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args) -#else -#define DEBPRINT(fmt, args...) do {} while (0) -#endif /* DEBUGGING */ - -extern int ide_noacpi; -extern int ide_noacpitfs; -extern int ide_noacpionboot; - -/** - * ide_get_dev_handle - finds acpi_handle and PCI device.function - * @dev: device to locate - * @handle: returned acpi_handle for @dev - * @pcidevfn: return PCI device.func for @dev - * - * Returns the ACPI object handle to the corresponding PCI device. - * - * Returns 0 on success, <0 on error. - */ -static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, - acpi_integer *pcidevfn) -{ - struct pci_dev *pdev = to_pci_dev(dev); - unsigned int bus, devnum, func; - acpi_integer addr; - acpi_handle dev_handle; - struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER, - .pointer = NULL}; - acpi_status status; - struct acpi_device_info *dinfo = NULL; - int ret = -ENODEV; - - bus = pdev->bus->number; - devnum = PCI_SLOT(pdev->devfn); - func = PCI_FUNC(pdev->devfn); - /* ACPI _ADR encoding for PCI bus: */ - addr = (acpi_integer)(devnum << 16 | func); - - DEBPRINT("ENTER: pci %02x:%02x.%01x\n", bus, devnum, func); - - dev_handle = DEVICE_ACPI_HANDLE(dev); - if (!dev_handle) { - DEBPRINT("no acpi handle for device\n"); - goto err; - } - - status = acpi_get_object_info(dev_handle, &buffer); - if (ACPI_FAILURE(status)) { - DEBPRINT("get_object_info for device failed\n"); - goto err; - } - dinfo = buffer.pointer; - if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && - dinfo->address == addr) { - *pcidevfn = addr; - *handle = dev_handle; - } else { - DEBPRINT("get_object_info for device has wrong " - " address: %llu, should be %u\n", - dinfo ? (unsigned long long)dinfo->address : -1ULL, - (unsigned int)addr); - goto err; - } - - DEBPRINT("for dev=0x%x.%x, addr=0x%llx, *handle=0x%p\n", - devnum, func, (unsigned long long)addr, *handle); - ret = 0; -err: - kfree(dinfo); - return ret; -} - -/** - * ide_acpi_hwif_get_handle - Get ACPI object handle for a given hwif - * @hwif: device to locate - * - * Retrieves the object handle for a given hwif. - * - * Returns handle on success, 0 on error. - */ -static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif) -{ - struct device *dev = hwif->gendev.parent; - acpi_handle dev_handle; - acpi_integer pcidevfn; - acpi_handle chan_handle; - int err; - - DEBPRINT("ENTER: device %s\n", hwif->name); - - if (!dev) { - DEBPRINT("no PCI device for %s\n", hwif->name); - return NULL; - } - - err = ide_get_dev_handle(dev, &dev_handle, &pcidevfn); - if (err < 0) { - DEBPRINT("ide_get_dev_handle failed (%d)\n", err); - return NULL; - } - - /* get child objects of dev_handle == channel objects, - * + _their_ children == drive objects */ - /* channel is hwif->channel */ - chan_handle = acpi_get_child(dev_handle, hwif->channel); - DEBPRINT("chan adr=%d: handle=0x%p\n", - hwif->channel, chan_handle); - - return chan_handle; -} - -/** - * ide_acpi_drive_get_handle - Get ACPI object handle for a given drive - * @drive: device to locate - * - * Retrieves the object handle of a given drive. According to the ACPI - * spec the drive is a child of the hwif. - * - * Returns handle on success, 0 on error. - */ -static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - int port; - acpi_handle drive_handle; - - if (!hwif->acpidata) - return NULL; - - if (!hwif->acpidata->obj_handle) - return NULL; - - port = hwif->channel ? drive->dn - 2: drive->dn; - - DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", - drive->name, hwif->channel, port); - - - /* TBD: could also check ACPI object VALID bits */ - drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port); - DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle); - - return drive_handle; -} - -/** - * do_drive_get_GTF - get the drive bootup default taskfile settings - * @drive: the drive for which the taskfile settings should be retrieved - * @gtf_length: number of bytes of _GTF data returned at @gtf_address - * @gtf_address: buffer containing _GTF taskfile arrays - * - * The _GTF method has no input parameters. - * It returns a variable number of register set values (registers - * hex 1F1..1F7, taskfiles). - * The is not known in advance, so have ACPI-CA - * allocate the buffer as needed and return it, then free it later. - * - * The returned @gtf_length and @gtf_address are only valid if the - * function return value is 0. - */ -static int do_drive_get_GTF(ide_drive_t *drive, - unsigned int *gtf_length, unsigned long *gtf_address, - unsigned long *obj_loc) -{ - acpi_status status; - struct acpi_buffer output; - union acpi_object *out_obj; - ide_hwif_t *hwif = HWIF(drive); - struct device *dev = hwif->gendev.parent; - int err = -ENODEV; - int port; - - *gtf_length = 0; - *gtf_address = 0UL; - *obj_loc = 0UL; - - if (ide_noacpi) - return 0; - - if (!dev) { - DEBPRINT("no PCI device for %s\n", hwif->name); - goto out; - } - - if (!hwif->acpidata) { - DEBPRINT("no ACPI data for %s\n", hwif->name); - goto out; - } - - port = hwif->channel ? drive->dn - 2: drive->dn; - - if (!drive->acpidata) { - if (port == 0) { - drive->acpidata = &hwif->acpidata->master; - hwif->acpidata->master.drive = drive; - } else { - drive->acpidata = &hwif->acpidata->slave; - hwif->acpidata->slave.drive = drive; - } - } - - DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", - hwif->name, dev->bus_id, port, hwif->channel); - - if (!drive->present) { - DEBPRINT("%s drive %d:%d not present\n", - hwif->name, hwif->channel, port); - goto out; - } - - /* Get this drive's _ADR info. if not already known. */ - if (!drive->acpidata->obj_handle) { - drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); - if (!drive->acpidata->obj_handle) { - DEBPRINT("No ACPI object found for %s\n", - drive->name); - goto out; - } - } - - /* Setting up output buffer */ - output.length = ACPI_ALLOCATE_BUFFER; - output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ - - /* _GTF has no input parameters */ - err = -EIO; - status = acpi_evaluate_object(drive->acpidata->obj_handle, "_GTF", - NULL, &output); - if (ACPI_FAILURE(status)) { - printk(KERN_DEBUG - "%s: Run _GTF error: status = 0x%x\n", - __FUNCTION__, status); - goto out; - } - - if (!output.length || !output.pointer) { - DEBPRINT("Run _GTF: " - "length or ptr is NULL (0x%llx, 0x%p)\n", - (unsigned long long)output.length, - output.pointer); - goto out; - } - - out_obj = output.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) { - DEBPRINT("Run _GTF: error: " - "expected object type of ACPI_TYPE_BUFFER, " - "got 0x%x\n", out_obj->type); - err = -ENOENT; - kfree(output.pointer); - goto out; - } - - if (!out_obj->buffer.length || !out_obj->buffer.pointer || - out_obj->buffer.length % REGS_PER_GTF) { - printk(KERN_ERR - "%s: unexpected GTF length (%d) or addr (0x%p)\n", - __FUNCTION__, out_obj->buffer.length, - out_obj->buffer.pointer); - err = -ENOENT; - kfree(output.pointer); - goto out; - } - - *gtf_length = out_obj->buffer.length; - *gtf_address = (unsigned long)out_obj->buffer.pointer; - *obj_loc = (unsigned long)out_obj; - DEBPRINT("returning gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n", - *gtf_length, *gtf_address, *obj_loc); - err = 0; -out: - return err; -} - -/** - * taskfile_load_raw - send taskfile registers to drive - * @drive: drive to which output is sent - * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) - * - * Outputs IDE taskfile to the drive. - */ -static int taskfile_load_raw(ide_drive_t *drive, - const struct taskfile_array *gtf) -{ - ide_task_t args; - int err = 0; - - DEBPRINT("(0x1f1-1f7): hex: " - "%02x %02x %02x %02x %02x %02x %02x\n", - gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], - gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); - - memset(&args, 0, sizeof(ide_task_t)); - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.data_phase = TASKFILE_IN; - args.handler = &task_no_data_intr; - - /* convert gtf to IDE Taskfile */ - args.tfRegister[1] = gtf->tfa[0]; /* 0x1f1 */ - args.tfRegister[2] = gtf->tfa[1]; /* 0x1f2 */ - args.tfRegister[3] = gtf->tfa[2]; /* 0x1f3 */ - args.tfRegister[4] = gtf->tfa[3]; /* 0x1f4 */ - args.tfRegister[5] = gtf->tfa[4]; /* 0x1f5 */ - args.tfRegister[6] = gtf->tfa[5]; /* 0x1f6 */ - args.tfRegister[7] = gtf->tfa[6]; /* 0x1f7 */ - - if (ide_noacpitfs) { - DEBPRINT("_GTF execution disabled\n"); - return err; - } - - err = ide_raw_taskfile(drive, &args, NULL); - if (err) - printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n", - __FUNCTION__, err); - - return err; -} - -/** - * do_drive_set_taskfiles - write the drive taskfile settings from _GTF - * @drive: the drive to which the taskfile command should be sent - * @gtf_length: total number of bytes of _GTF taskfiles - * @gtf_address: location of _GTF taskfile arrays - * - * Write {gtf_address, length gtf_length} in groups of - * REGS_PER_GTF bytes. - */ -static int do_drive_set_taskfiles(ide_drive_t *drive, - unsigned int gtf_length, - unsigned long gtf_address) -{ - int rc = -ENODEV, err; - int gtf_count = gtf_length / REGS_PER_GTF; - int ix; - struct taskfile_array *gtf; - - if (ide_noacpi) - return 0; - - DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn); - - if (!drive->present) - goto out; - if (!gtf_count) /* shouldn't be here */ - goto out; - - DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n", - gtf_length, gtf_length, gtf_count, gtf_address); - - if (gtf_length % REGS_PER_GTF) { - printk(KERN_ERR "%s: unexpected GTF length (%d)\n", - __FUNCTION__, gtf_length); - goto out; - } - - rc = 0; - for (ix = 0; ix < gtf_count; ix++) { - gtf = (struct taskfile_array *) - (gtf_address + ix * REGS_PER_GTF); - - /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ - err = taskfile_load_raw(drive, gtf); - if (err) - rc = err; - } - -out: - return rc; -} - -/** - * ide_acpi_exec_tfs - get then write drive taskfile settings - * @drive: the drive for which the taskfile settings should be - * written. - * - * According to the ACPI spec this should be called after _STM - * has been evaluated for the interface. Some ACPI vendors interpret - * that as a hard requirement and modify the taskfile according - * to the Identify Drive information passed down with _STM. - * So one should really make sure to call this only after _STM has - * been executed. - */ -int ide_acpi_exec_tfs(ide_drive_t *drive) -{ - int ret; - unsigned int gtf_length; - unsigned long gtf_address; - unsigned long obj_loc; - - if (ide_noacpi) - return 0; - - DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn); - - ret = do_drive_get_GTF(drive, >f_length, >f_address, &obj_loc); - if (ret < 0) { - DEBPRINT("get_GTF error (%d)\n", ret); - return ret; - } - - DEBPRINT("call set_taskfiles, drive=%s\n", drive->name); - - ret = do_drive_set_taskfiles(drive, gtf_length, gtf_address); - kfree((void *)obj_loc); - if (ret < 0) { - DEBPRINT("set_taskfiles error (%d)\n", ret); - } - - DEBPRINT("ret=%d\n", ret); - - return ret; -} -EXPORT_SYMBOL_GPL(ide_acpi_exec_tfs); - -/** - * ide_acpi_get_timing - get the channel (controller) timings - * @hwif: target IDE interface (channel) - * - * This function executes the _GTM ACPI method for the target channel. - * - */ -void ide_acpi_get_timing(ide_hwif_t *hwif) -{ - acpi_status status; - struct acpi_buffer output; - union acpi_object *out_obj; - - if (ide_noacpi) - return; - - DEBPRINT("ENTER:\n"); - - if (!hwif->acpidata) { - DEBPRINT("no ACPI data for %s\n", hwif->name); - return; - } - - /* Setting up output buffer for _GTM */ - output.length = ACPI_ALLOCATE_BUFFER; - output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ - - /* _GTM has no input parameters */ - status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_GTM", - NULL, &output); - - DEBPRINT("_GTM status: %d, outptr: 0x%p, outlen: 0x%llx\n", - status, output.pointer, - (unsigned long long)output.length); - - if (ACPI_FAILURE(status)) { - DEBPRINT("Run _GTM error: status = 0x%x\n", status); - return; - } - - if (!output.length || !output.pointer) { - DEBPRINT("Run _GTM: length or ptr is NULL (0x%llx, 0x%p)\n", - (unsigned long long)output.length, - output.pointer); - kfree(output.pointer); - return; - } - - out_obj = output.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) { - kfree(output.pointer); - DEBPRINT("Run _GTM: error: " - "expected object type of ACPI_TYPE_BUFFER, " - "got 0x%x\n", out_obj->type); - return; - } - - if (!out_obj->buffer.length || !out_obj->buffer.pointer || - out_obj->buffer.length != sizeof(struct GTM_buffer)) { - kfree(output.pointer); - printk(KERN_ERR - "%s: unexpected _GTM length (0x%x)[should be 0x%zx] or " - "addr (0x%p)\n", - __FUNCTION__, out_obj->buffer.length, - sizeof(struct GTM_buffer), out_obj->buffer.pointer); - return; - } - - memcpy(&hwif->acpidata->gtm, out_obj->buffer.pointer, - sizeof(struct GTM_buffer)); - - DEBPRINT("_GTM info: ptr: 0x%p, len: 0x%x, exp.len: 0x%Zx\n", - out_obj->buffer.pointer, out_obj->buffer.length, - sizeof(struct GTM_buffer)); - - DEBPRINT("_GTM fields: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", - hwif->acpidata->gtm.PIO_speed0, - hwif->acpidata->gtm.DMA_speed0, - hwif->acpidata->gtm.PIO_speed1, - hwif->acpidata->gtm.DMA_speed1, - hwif->acpidata->gtm.GTM_flags); - - kfree(output.pointer); -} -EXPORT_SYMBOL_GPL(ide_acpi_get_timing); - -/** - * ide_acpi_push_timing - set the channel (controller) timings - * @hwif: target IDE interface (channel) - * - * This function executes the _STM ACPI method for the target channel. - * - * _STM requires Identify Drive data, which has to passed as an argument. - * Unfortunately hd_driveid is a mangled version which we can't readily - * use; hence we'll get the information afresh. - */ -void ide_acpi_push_timing(ide_hwif_t *hwif) -{ - acpi_status status; - struct acpi_object_list input; - union acpi_object in_params[3]; - struct ide_acpi_drive_link *master = &hwif->acpidata->master; - struct ide_acpi_drive_link *slave = &hwif->acpidata->slave; - - if (ide_noacpi) - return; - - DEBPRINT("ENTER:\n"); - - if (!hwif->acpidata) { - DEBPRINT("no ACPI data for %s\n", hwif->name); - return; - } - - /* Give the GTM buffer + drive Identify data to the channel via the - * _STM method: */ - /* setup input parameters buffer for _STM */ - input.count = 3; - input.pointer = in_params; - in_params[0].type = ACPI_TYPE_BUFFER; - in_params[0].buffer.length = sizeof(struct GTM_buffer); - in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm; - in_params[1].type = ACPI_TYPE_BUFFER; - in_params[1].buffer.length = sizeof(struct hd_driveid); - in_params[1].buffer.pointer = (u8 *)&master->idbuff; - in_params[2].type = ACPI_TYPE_BUFFER; - in_params[2].buffer.length = sizeof(struct hd_driveid); - in_params[2].buffer.pointer = (u8 *)&slave->idbuff; - /* Output buffer: _STM has no output */ - - status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_STM", - &input, NULL); - - if (ACPI_FAILURE(status)) { - DEBPRINT("Run _STM error: status = 0x%x\n", status); - } - DEBPRINT("_STM status: %d\n", status); -} -EXPORT_SYMBOL_GPL(ide_acpi_push_timing); - -/** - * ide_acpi_init - initialize the ACPI link for an IDE interface - * @hwif: target IDE interface (channel) - * - * The ACPI spec is not quite clear when the drive identify buffer - * should be obtained. Calling IDENTIFY DEVICE during shutdown - * is not the best of ideas as the drive might already being put to - * sleep. And obviously we can't call it during resume. - * So we get the information during startup; but this means that - * any changes during run-time will be lost after resume. - */ -void ide_acpi_init(ide_hwif_t *hwif) -{ - int unit; - int err; - struct ide_acpi_drive_link *master; - struct ide_acpi_drive_link *slave; - - hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL); - if (!hwif->acpidata) - return; - - hwif->acpidata->obj_handle = ide_acpi_hwif_get_handle(hwif); - if (!hwif->acpidata->obj_handle) { - DEBPRINT("no ACPI object for %s found\n", hwif->name); - kfree(hwif->acpidata); - hwif->acpidata = NULL; - return; - } - - /* - * The ACPI spec mandates that we send information - * for both drives, regardless whether they are connected - * or not. - */ - hwif->acpidata->master.drive = &hwif->drives[0]; - hwif->drives[0].acpidata = &hwif->acpidata->master; - master = &hwif->acpidata->master; - - hwif->acpidata->slave.drive = &hwif->drives[1]; - hwif->drives[1].acpidata = &hwif->acpidata->slave; - slave = &hwif->acpidata->slave; - - - /* - * Send IDENTIFY for each drive - */ - if (master->drive->present) { - err = taskfile_lib_get_identify(master->drive, master->idbuff); - if (err) { - DEBPRINT("identify device %s failed (%d)\n", - master->drive->name, err); - } - } - - if (slave->drive->present) { - err = taskfile_lib_get_identify(slave->drive, slave->idbuff); - if (err) { - DEBPRINT("identify device %s failed (%d)\n", - slave->drive->name, err); - } - } - - if (ide_noacpionboot) { - DEBPRINT("ACPI methods disabled on boot\n"); - return; - } - - /* - * ACPI requires us to call _STM on startup - */ - ide_acpi_get_timing(hwif); - ide_acpi_push_timing(hwif); - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - ide_drive_t *drive = &hwif->drives[unit]; - - if (drive->present) { - /* Execute ACPI startup code */ - ide_acpi_exec_tfs(drive); - } - } -} -EXPORT_SYMBOL_GPL(ide_acpi_init); diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index 176bbc850d6b..5a5c565a32a8 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -1384,9 +1384,6 @@ static int hwif_init(ide_hwif_t *hwif) done: init_gendisk(hwif); - - ide_acpi_init(hwif); - hwif->present = 1; /* success */ return 1; diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c index c750f6ce770a..6c9bd5165bdb 100644 --- a/trunk/drivers/ide/ide.c +++ b/trunk/drivers/ide/ide.c @@ -187,12 +187,6 @@ int noautodma = 1; EXPORT_SYMBOL(noautodma); -#ifdef CONFIG_BLK_DEV_IDEACPI -int ide_noacpi = 0; -int ide_noacpitfs = 1; -int ide_noacpionboot = 1; -#endif - /* * This is declared extern in ide.h, for access by other IDE modules: */ @@ -1220,15 +1214,10 @@ EXPORT_SYMBOL(system_bus_clock); static int generic_ide_suspend(struct device *dev, pm_message_t mesg) { ide_drive_t *drive = dev->driver_data; - ide_hwif_t *hwif = HWIF(drive); struct request rq; struct request_pm_state rqpm; ide_task_t args; - /* Call ACPI _GTM only once */ - if (!(drive->dn % 2)) - ide_acpi_get_timing(hwif); - memset(&rq, 0, sizeof(rq)); memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); @@ -1246,17 +1235,10 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg) static int generic_ide_resume(struct device *dev) { ide_drive_t *drive = dev->driver_data; - ide_hwif_t *hwif = HWIF(drive); struct request rq; struct request_pm_state rqpm; ide_task_t args; - /* Call ACPI _STM only once */ - if (!(drive->dn % 2)) - ide_acpi_push_timing(hwif); - - ide_acpi_exec_tfs(drive); - memset(&rq, 0, sizeof(rq)); memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); @@ -1561,24 +1543,6 @@ static int __init ide_setup(char *s) } #endif /* CONFIG_BLK_DEV_IDEPCI */ -#ifdef CONFIG_BLK_DEV_IDEACPI - if (!strcmp(s, "ide=noacpi")) { - //printk(" : Disable IDE ACPI support.\n"); - ide_noacpi = 1; - return 1; - } - if (!strcmp(s, "ide=acpigtf")) { - //printk(" : Enable IDE ACPI _GTF support.\n"); - ide_noacpitfs = 0; - return 1; - } - if (!strcmp(s, "ide=acpionboot")) { - //printk(" : Call IDE ACPI methods on boot.\n"); - ide_noacpionboot = 0; - return 1; - } -#endif /* CONFIG_BLK_DEV_IDEACPI */ - /* * Look for drive options: "hdx=" */ diff --git a/trunk/drivers/ide/pci/Makefile b/trunk/drivers/ide/pci/Makefile index 6591ff4753cb..fef08960aa4c 100644 --- a/trunk/drivers/ide/pci/Makefile +++ b/trunk/drivers/ide/pci/Makefile @@ -9,10 +9,9 @@ obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o -obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o -obj-$(CONFIG_BLK_DEV_IT8213) += it8213.o +#obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o obj-$(CONFIG_BLK_DEV_JMICRON) += jmicron.o obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o @@ -27,7 +26,6 @@ obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o -obj-$(CONFIG_BLK_DEV_TC86C001) += tc86c001.o obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o diff --git a/trunk/drivers/ide/pci/delkin_cb.c b/trunk/drivers/ide/pci/delkin_cb.c deleted file mode 100644 index e2672fc65d30..000000000000 --- a/trunk/drivers/ide/pci/delkin_cb.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * linux/drivers/ide/pci/delkin_cb.c - * - * Created 20 Oct 2004 by Mark Lord - * - * Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter - * - * Modeled after the 16-bit PCMCIA driver: ide-cs.c - * - * This is slightly peculiar, in that it is a PCI driver, - * but is NOT an IDE PCI driver -- the IDE layer does not directly - * support hot insertion/removal of PCI interfaces, so this driver - * is unable to use the IDE PCI interfaces. Instead, it uses the - * same interfaces as the ide-cs (PCMCIA) driver uses. - * On the plus side, the driver is also smaller/simpler this way. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * No chip documentation has yet been found, - * so these configuration values were pulled from - * a running Win98 system using "debug". - * This gives around 3MByte/second read performance, - * which is about 2/3 of what the chip is capable of. - * - * There is also a 4KByte mmio region on the card, - * but its purpose has yet to be reverse-engineered. - */ -static const u8 setup[] = { - 0x00, 0x05, 0xbe, 0x01, 0x20, 0x8f, 0x00, 0x00, - 0xa4, 0x1f, 0xb3, 0x1b, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13, -}; - -static int __devinit -delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) -{ - unsigned long base; - hw_regs_t hw; - ide_hwif_t *hwif = NULL; - ide_drive_t *drive; - int i, rc; - - rc = pci_enable_device(dev); - if (rc) { - printk(KERN_ERR "delkin_cb: pci_enable_device failed (%d)\n", rc); - return rc; - } - rc = pci_request_regions(dev, "delkin_cb"); - if (rc) { - printk(KERN_ERR "delkin_cb: pci_request_regions failed (%d)\n", rc); - pci_disable_device(dev); - return rc; - } - base = pci_resource_start(dev, 0); - outb(0x02, base + 0x1e); /* set nIEN to block interrupts */ - inb(base + 0x17); /* read status to clear interrupts */ - for (i = 0; i < sizeof(setup); ++i) { - if (setup[i]) - outb(setup[i], base + i); - } - pci_release_regions(dev); /* IDE layer handles regions itself */ - - memset(&hw, 0, sizeof(hw)); - ide_std_init_ports(&hw, base + 0x10, base + 0x1e); - hw.irq = dev->irq; - hw.chipset = ide_pci; /* this enables IRQ sharing */ - - rc = ide_register_hw_with_fixup(&hw, &hwif, ide_undecoded_slave); - if (rc < 0) { - printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc); - pci_disable_device(dev); - return -ENODEV; - } - pci_set_drvdata(dev, hwif); - hwif->pci_dev = dev; - drive = &hwif->drives[0]; - if (drive->present) { - drive->io_32bit = 1; - drive->unmask = 1; - } - return 0; -} - -static void -delkin_cb_remove (struct pci_dev *dev) -{ - ide_hwif_t *hwif = pci_get_drvdata(dev); - - if (hwif) - ide_unregister(hwif->index); - pci_disable_device(dev); -} - -static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = { - { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl); - -static struct pci_driver driver = { - .name = "Delkin-ASKA-Workbit Cardbus IDE", - .id_table = delkin_cb_pci_tbl, - .probe = delkin_cb_probe, - .remove = delkin_cb_remove, -}; - -static int -delkin_cb_init (void) -{ - return pci_module_init(&driver); -} - -static void -delkin_cb_exit (void) -{ - pci_unregister_driver(&driver); -} - -module_init(delkin_cb_init); -module_exit(delkin_cb_exit); - -MODULE_AUTHOR("Mark Lord"); -MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/drivers/ide/pci/hpt366.c b/trunk/drivers/ide/pci/hpt366.c index 05be8fadda7a..b486442dd5d7 100644 --- a/trunk/drivers/ide/pci/hpt366.c +++ b/trunk/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 1.01 Dec 23, 2006 + * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -60,10 +60,13 @@ * channel caused the cached register value to get out of sync with the * actual one, the channels weren't serialized, the turnaround shouldn't * be done on 66 MHz PCI bus - * - disable UltraATA/100 for HPT370 by default as the 33 MHz clock being used - * does not allow for this speed anyway - * - avoid touching disabled channels (e.g. HPT371/N are single channel chips, - * their primary channel is kind of virtual, it isn't tied to any pins) + * - avoid calibrating PLL twice as the second time results in a wrong PCI + * frequency and thus in the wrong timings for the secondary channel + * - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not + * allow for this speed anyway) + * - add support for HPT302N and HPT371N clocking (the same as for HPT372N) + * - HPT371/N are single channel chips, so avoid touching the primary channel + * which exists only virtually (there's no pins for it) * - fix/remove bad/unused timing tables and use one set of tables for the whole * HPT37x chip family; save space by introducing the separate transfer mode * table in which the mode lookup is done @@ -73,47 +76,11 @@ * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead * - pass to init_chipset() handlers a copy of the IDE PCI device structure as * they tamper with its fields - * - pass to the init_setup handlers a copy of the ide_pci_device_t structure - * since they may tamper with its fields - * - prefix the driver startup messages with the real chip name - * - claim the extra 240 bytes of I/O space for all chips - * - optimize the rate masking/filtering and the drive list lookup code - * - use pci_get_slot() to get to the function 1 of HPT36x/374 - * - cache offset of the channel's misc. control registers (MCRs) being used - * throughout the driver - * - only touch the relevant MCR when detecting the cable type on HPT374's - * function 1 - * - rename all the register related variables consistently - * - move all the interrupt twiddling code from the speedproc handlers into - * init_hwif_hpt366(), also grouping all the DMA related code together there - * - merge two HPT37x speedproc handlers, fix the PIO timing register mask and - * separate the UltraDMA and MWDMA masks there to avoid changing PIO timings - * when setting an UltraDMA mode - * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select - * the best possible one - * - clean up DMA timeout handling for HPT370 - * - switch to using the enumeration type to differ between the numerous chip - * variants, matching PCI device/revision ID with the chip type early, at the - * init_setup stage - * - extend the hpt_info structure to hold the DPLL and PCI clock frequencies, - * stop duplicating it for each channel by storing the pointer in the pci_dev - * structure: first, at the init_setup stage, point it to a static "template" - * with only the chip type and its specific base DPLL frequency, the highest - * supported DMA mode, and the chip settings table pointer filled, then, at - * the init_chipset stage, allocate per-chip instance and fill it with the - * rest of the necessary information - * - get rid of the constant thresholds in the HPT37x PCI clock detection code, - * switch to calculating PCI clock frequency based on the chip's base DPLL - * frequency - * - switch to using the DPLL clock and enable UltraATA/133 mode by default on - * anything newer than HPT370/A - * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(), - * also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips; - * unify HPT36x/37x timing setup code and the speedproc handlers by joining - * the register setting lists into the table indexed by the clock selected - * Sergei Shtylyov, or + * + * */ + #include #include #include @@ -365,159 +332,93 @@ static u32 sixty_six_base_hpt37x[] = { }; #define HPT366_DEBUG_DRIVE_INFO 0 -#define HPT374_ALLOW_ATA133_6 1 -#define HPT371_ALLOW_ATA133_6 1 -#define HPT302_ALLOW_ATA133_6 1 -#define HPT372_ALLOW_ATA133_6 1 -#define HPT370_ALLOW_ATA100_5 0 +#define HPT374_ALLOW_ATA133_6 0 +#define HPT371_ALLOW_ATA133_6 0 +#define HPT302_ALLOW_ATA133_6 0 +#define HPT372_ALLOW_ATA133_6 0 +#define HPT370_ALLOW_ATA100_5 1 #define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_3 1 #define HPT366_MAX_DEVS 8 -/* Supported ATA clock frequencies */ -enum ata_clock { - ATA_CLOCK_25MHZ, - ATA_CLOCK_33MHZ, - ATA_CLOCK_40MHZ, - ATA_CLOCK_50MHZ, - ATA_CLOCK_66MHZ, - NUM_ATA_CLOCKS -}; +#define F_LOW_PCI_33 0x23 +#define F_LOW_PCI_40 0x29 +#define F_LOW_PCI_50 0x2d +#define F_LOW_PCI_66 0x42 /* - * Hold all the HighPoint chip information in one place. + * Hold all the highpoint quirks and revision information in one + * place. */ -struct hpt_info { - u8 chip_type; /* Chip type */ +struct hpt_info +{ u8 max_mode; /* Speeds allowed */ - u8 dpll_clk; /* DPLL clock in MHz */ - u8 pci_clk; /* PCI clock in MHz */ - u32 **settings; /* Chipset settings table */ -}; - -/* Supported HighPoint chips */ -enum { - HPT36x, - HPT370, - HPT370A, - HPT374, - HPT372, - HPT372A, - HPT302, - HPT371, - HPT372N, - HPT302N, - HPT371N -}; - -static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = { - twenty_five_base_hpt36x, - thirty_three_base_hpt36x, - forty_base_hpt36x, - NULL, - NULL -}; - -static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = { - NULL, - thirty_three_base_hpt37x, - NULL, - fifty_base_hpt37x, - sixty_six_base_hpt37x -}; - -static struct hpt_info hpt36x __devinitdata = { - .chip_type = HPT36x, - .max_mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1, - .dpll_clk = 0, /* no DPLL */ - .settings = hpt36x_settings -}; - -static struct hpt_info hpt370 __devinitdata = { - .chip_type = HPT370, - .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2, - .dpll_clk = 48, - .settings = hpt37x_settings -}; - -static struct hpt_info hpt370a __devinitdata = { - .chip_type = HPT370A, - .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2, - .dpll_clk = 48, - .settings = hpt37x_settings -}; - -static struct hpt_info hpt374 __devinitdata = { - .chip_type = HPT374, - .max_mode = HPT374_ALLOW_ATA133_6 ? 4 : 3, - .dpll_clk = 48, - .settings = hpt37x_settings -}; - -static struct hpt_info hpt372 __devinitdata = { - .chip_type = HPT372, - .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3, - .dpll_clk = 55, - .settings = hpt37x_settings -}; - -static struct hpt_info hpt372a __devinitdata = { - .chip_type = HPT372A, - .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3, - .dpll_clk = 66, - .settings = hpt37x_settings + int revision; /* Chipset revision */ + int flags; /* Chipset properties */ +#define PLL_MODE 1 +#define IS_3xxN 2 +#define PCI_66MHZ 4 + /* Speed table */ + u32 *speed; }; -static struct hpt_info hpt302 __devinitdata = { - .chip_type = HPT302, - .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3, - .dpll_clk = 66, - .settings = hpt37x_settings -}; - -static struct hpt_info hpt371 __devinitdata = { - .chip_type = HPT371, - .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3, - .dpll_clk = 66, - .settings = hpt37x_settings -}; - -static struct hpt_info hpt372n __devinitdata = { - .chip_type = HPT372N, - .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3, - .dpll_clk = 77, - .settings = hpt37x_settings -}; - -static struct hpt_info hpt302n __devinitdata = { - .chip_type = HPT302N, - .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3, - .dpll_clk = 77, -}; - -static struct hpt_info hpt371n __devinitdata = { - .chip_type = HPT371N, - .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3, - .dpll_clk = 77, - .settings = hpt37x_settings -}; +/* + * This wants fixing so that we do everything not by classrev + * (which breaks on the newest chips) but by creating an + * enumeration of chip variants and using that + */ -static int check_in_drive_list(ide_drive_t *drive, const char **list) +static __devinit u32 hpt_revision (struct pci_dev *dev) { - struct hd_driveid *id = drive->id; - - while (*list) - if (!strcmp(*list++,id->model)) - return 1; - return 0; + u32 class_rev; + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + switch(dev->device) { + /* Remap new 372N onto 372 */ + case PCI_DEVICE_ID_TTI_HPT372N: + class_rev = PCI_DEVICE_ID_TTI_HPT372; break; + case PCI_DEVICE_ID_TTI_HPT374: + class_rev = PCI_DEVICE_ID_TTI_HPT374; break; + case PCI_DEVICE_ID_TTI_HPT371: + class_rev = PCI_DEVICE_ID_TTI_HPT371; break; + case PCI_DEVICE_ID_TTI_HPT302: + class_rev = PCI_DEVICE_ID_TTI_HPT302; break; + case PCI_DEVICE_ID_TTI_HPT372: + class_rev = PCI_DEVICE_ID_TTI_HPT372; break; + default: + break; + } + return class_rev; } -static u8 hpt3xx_ratemask(ide_drive_t *drive) -{ - struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); - u8 mode = info->max_mode; +static int check_in_drive_lists(ide_drive_t *drive, const char **list); +static u8 hpt3xx_ratemask (ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct hpt_info *info = ide_get_hwifdata(hwif); + u8 mode = 0; + + /* FIXME: TODO - move this to set info->mode once at boot */ + + if (info->revision >= 8) { /* HPT374 */ + mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3; + } else if (info->revision >= 7) { /* HPT371 */ + mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3; + } else if (info->revision >= 6) { /* HPT302 */ + mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3; + } else if (info->revision >= 5) { /* HPT372 */ + mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3; + } else if (info->revision >= 4) { /* HPT370A */ + mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; + } else if (info->revision >= 3) { /* HPT370 */ + mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; + mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode; + } else { /* HPT366 and HPT368 */ + mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2; + } if (!eighty_ninty_three(drive) && mode) mode = min(mode, (u8)1); return mode; @@ -528,61 +429,75 @@ static u8 hpt3xx_ratemask(ide_drive_t *drive) * either PIO or UDMA modes 0,4,5 */ -static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) +static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) { - struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); - u8 chip_type = info->chip_type; + ide_hwif_t *hwif = drive->hwif; + struct hpt_info *info = ide_get_hwifdata(hwif); u8 mode = hpt3xx_ratemask(drive); if (drive->media != ide_disk) return min(speed, (u8)XFER_PIO_4); - switch (mode) { + switch(mode) { case 0x04: - speed = min_t(u8, speed, XFER_UDMA_6); + speed = min(speed, (u8)XFER_UDMA_6); break; case 0x03: - speed = min_t(u8, speed, XFER_UDMA_5); - if (chip_type >= HPT374) + speed = min(speed, (u8)XFER_UDMA_5); + if (info->revision >= 5) break; - if (!check_in_drive_list(drive, bad_ata100_5)) - goto check_bad_ata33; - /* fall thru */ + if (check_in_drive_lists(drive, bad_ata100_5)) + speed = min(speed, (u8)XFER_UDMA_4); + break; case 0x02: - speed = min_t(u8, speed, XFER_UDMA_4); - - /* - * CHECK ME, Does this need to be changed to HPT374 ?? - */ - if (chip_type >= HPT370) - goto check_bad_ata33; - if (HPT366_ALLOW_ATA66_4 && - !check_in_drive_list(drive, bad_ata66_4)) - goto check_bad_ata33; - - speed = min_t(u8, speed, XFER_UDMA_3); - if (HPT366_ALLOW_ATA66_3 && - !check_in_drive_list(drive, bad_ata66_3)) - goto check_bad_ata33; - /* fall thru */ - case 0x01: - speed = min_t(u8, speed, XFER_UDMA_2); - - check_bad_ata33: - if (chip_type >= HPT370A) + speed = min(speed, (u8)XFER_UDMA_4); + /* + * CHECK ME, Does this need to be set to 5 ?? + */ + if (info->revision >= 3) break; - if (!check_in_drive_list(drive, bad_ata33)) + if ((check_in_drive_lists(drive, bad_ata66_4)) || + (!(HPT366_ALLOW_ATA66_4))) + speed = min(speed, (u8)XFER_UDMA_3); + if ((check_in_drive_lists(drive, bad_ata66_3)) || + (!(HPT366_ALLOW_ATA66_3))) + speed = min(speed, (u8)XFER_UDMA_2); + break; + case 0x01: + speed = min(speed, (u8)XFER_UDMA_2); + /* + * CHECK ME, Does this need to be set to 5 ?? + */ + if (info->revision >= 3) break; - /* fall thru */ + if (check_in_drive_lists(drive, bad_ata33)) + speed = min(speed, (u8)XFER_MW_DMA_2); + break; case 0x00: default: - speed = min_t(u8, speed, XFER_MW_DMA_2); + speed = min(speed, (u8)XFER_MW_DMA_2); break; } return speed; } -static u32 get_speed_setting(u8 speed, struct hpt_info *info) +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + struct hd_driveid *id = drive->id; + + if (quirk_drives == list) { + while (*list) + if (strstr(id->model, *list++)) + return 1; + } else { + while (*list) + if (!strcmp(*list++,id->model)) + return 1; + } + return 0; +} + +static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) { int i; @@ -595,161 +510,228 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info) for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) if (xfer_speeds[i] == speed) break; - /* - * NOTE: info->settings only points to the pointer - * to the list of the actual register values - */ - return (*info->settings)[i]; + return chipset_table[i]; } static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = pci_get_drvdata(dev); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 itr_addr = drive->dn ? 0x44 : 0x40; - u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : - (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); - u32 new_itr = get_speed_setting(speed, info); - u32 old_itr = 0; + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata(hwif); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; + u8 regfast = (hwif->channel) ? 0x55 : 0x51; + u8 drive_fast = 0; + u32 reg1 = 0, reg2 = 0; /* - * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) - * to avoid problems handling I/O errors later + * Disable the "fast interrupt" prediction. */ - pci_read_config_dword(dev, itr_addr, &old_itr); - new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); - new_itr &= ~0xc0000000; + pci_read_config_byte(dev, regfast, &drive_fast); + if (drive_fast & 0x80) + pci_write_config_byte(dev, regfast, drive_fast & ~0x80); - pci_write_config_dword(dev, itr_addr, new_itr); + reg2 = pci_bus_clock_list(speed, info->speed); + + /* + * Disable on-chip PIO FIFO/buffer + * (to avoid problems handling I/O errors later) + */ + pci_read_config_dword(dev, regtime, ®1); + if (speed >= XFER_MW_DMA_0) { + reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); + } else { + reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000); + } + reg2 &= ~0x80000000; + + pci_write_config_dword(dev, regtime, reg2); return ide_config_drive_speed(drive, speed); } -static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed) +static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = pci_get_drvdata(dev); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 itr_addr = 0x40 + (drive->dn * 4); - u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : - (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); - u32 new_itr = get_speed_setting(speed, info); - u32 old_itr = 0; - - pci_read_config_dword(dev, itr_addr, &old_itr); - new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata(hwif); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; + u8 drive_pci = 0x40 + (drive->dn * 4); + u8 new_fast = 0, drive_fast = 0; + u32 list_conf = 0, drive_conf = 0; + u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + + /* + * Disable the "fast interrupt" prediction. + * don't holdoff on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, regfast, &drive_fast); + new_fast = drive_fast; + if (new_fast & 0x02) + new_fast &= ~0x02; + +#ifdef HPT_DELAY_INTERRUPT + if (new_fast & 0x01) + new_fast &= ~0x01; +#else + if ((new_fast & 0x01) == 0) + new_fast |= 0x01; +#endif + if (new_fast != drive_fast) + pci_write_config_byte(dev, regfast, new_fast); + + list_conf = pci_bus_clock_list(speed, info->speed); + + pci_read_config_dword(dev, drive_pci, &drive_conf); + list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); if (speed < XFER_MW_DMA_0) - new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - pci_write_config_dword(dev, itr_addr, new_itr); + list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + pci_write_config_dword(dev, drive_pci, list_conf); return ide_config_drive_speed(drive, speed); } -static int hpt3xx_tune_chipset(ide_drive_t *drive, u8 speed) +static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = HWIF(drive); - struct hpt_info *info = pci_get_drvdata(hwif->pci_dev); + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata(hwif); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; + u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4); + u32 list_conf = 0, drive_conf = 0; + u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + + /* + * Disable the "fast interrupt" prediction. + * don't holdoff on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, regfast, &drive_fast); + drive_fast &= ~0x07; + pci_write_config_byte(dev, regfast, drive_fast); + + list_conf = pci_bus_clock_list(speed, info->speed); + pci_read_config_dword(dev, drive_pci, &drive_conf); + list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); + if (speed < XFER_MW_DMA_0) + list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + pci_write_config_dword(dev, drive_pci, list_conf); + + return ide_config_drive_speed(drive, speed); +} - if (info->chip_type >= HPT370) - return hpt37x_tune_chipset(drive, speed); +static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed) +{ + ide_hwif_t *hwif = drive->hwif; + struct hpt_info *info = ide_get_hwifdata(hwif); + + if (info->revision >= 8) + return hpt372_tune_chipset(drive, speed); /* not a typo */ + else if (info->revision >= 5) + return hpt372_tune_chipset(drive, speed); + else if (info->revision >= 3) + return hpt370_tune_chipset(drive, speed); else /* hpt368: hpt_minimum_revision(dev, 2) */ return hpt36x_tune_chipset(drive, speed); } -static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio) +static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio) { - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - (void) hpt3xx_tune_chipset (drive, XFER_PIO_0 + pio); + pio = ide_get_best_pio_mode(drive, 255, pio, NULL); + (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio)); } /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. Initially designed for + * after the drive is reported by the OS. Initially for designed for * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. * + * check_in_drive_lists(drive, bad_ata66_4) + * check_in_drive_lists(drive, bad_ata66_3) + * check_in_drive_lists(drive, bad_ata33) + * */ -static int config_chipset_for_dma(ide_drive_t *drive) +static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); + ide_hwif_t *hwif = drive->hwif; + struct hpt_info *info = ide_get_hwifdata(hwif); if (!speed) return 0; + /* If we don't have any timings we can't do a lot */ + if (info->speed == NULL) + return 0; + (void) hpt3xx_tune_chipset(drive, speed); return ide_dma_enable(drive); } -static int hpt3xx_quirkproc(ide_drive_t *drive) +static int hpt3xx_quirkproc (ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - const char **list = quirk_drives; - - while (*list) - if (strstr(id->model, *list++)) - return 1; - return 0; + return ((int) check_in_drive_lists(drive, quirk_drives)); } -static void hpt3xx_intrproc(ide_drive_t *drive) +static void hpt3xx_intrproc (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = drive->hwif; if (drive->quirk_list) return; /* drives in the quirk_list may not like intr setups/cleanups */ - hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG); + hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); } -static void hpt3xx_maskproc(ide_drive_t *drive, int mask) +static void hpt3xx_maskproc (ide_drive_t *drive, int mask) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = pci_get_drvdata(dev); + ide_hwif_t *hwif = drive->hwif; + struct hpt_info *info = ide_get_hwifdata(hwif); + struct pci_dev *dev = hwif->pci_dev; if (drive->quirk_list) { - if (info->chip_type >= HPT370) { - u8 scr1 = 0; - - pci_read_config_byte(dev, 0x5a, &scr1); - if (((scr1 & 0x10) >> 4) != mask) { - if (mask) - scr1 |= 0x10; - else - scr1 &= ~0x10; - pci_write_config_byte(dev, 0x5a, scr1); - } + if (info->revision >= 3) { + u8 reg5a = 0; + pci_read_config_byte(dev, 0x5a, ®5a); + if (((reg5a & 0x10) >> 4) != mask) + pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); } else { - if (mask) + if (mask) { disable_irq(hwif->irq); - else - enable_irq (hwif->irq); + } else { + enable_irq(hwif->irq); + } } - } else - hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2), - IDE_CONTROL_REG); + } else { + if (IDE_CONTROL_REG) + hwif->OUTB(mask ? (drive->ctl | 2) : + (drive->ctl & ~2), + IDE_CONTROL_REG); + } } -static int hpt366_config_drive_xfer_rate(ide_drive_t *drive) +static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = drive->hwif; struct hd_driveid *id = drive->id; drive->init_speed = 0; if ((id->capability & 1) && drive->autodma) { - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); + + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); + } goto fast_ata_pio; } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: - hpt3xx_tune_drive(drive, 255); + hpt3xx_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } /* IORDY not supported */ @@ -757,48 +739,31 @@ static int hpt366_config_drive_xfer_rate(ide_drive_t *drive) } /* - * This is specific to the HPT366 UDMA chipset + * This is specific to the HPT366 UDMA bios chipset * by HighPoint|Triones Technologies, Inc. */ -static int hpt366_ide_dma_lostirq(ide_drive_t *drive) +static int hpt366_ide_dma_lostirq (ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 mcr1 = 0, mcr3 = 0, scr1 = 0; - - pci_read_config_byte(dev, 0x50, &mcr1); - pci_read_config_byte(dev, 0x52, &mcr3); - pci_read_config_byte(dev, 0x5a, &scr1); - printk("%s: (%s) mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n", - drive->name, __FUNCTION__, mcr1, mcr3, scr1); - if (scr1 & 0x10) - pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 reg50h = 0, reg52h = 0, reg5ah = 0; + + pci_read_config_byte(dev, 0x50, ®50h); + pci_read_config_byte(dev, 0x52, ®52h); + pci_read_config_byte(dev, 0x5a, ®5ah); + printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", + drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); + if (reg5ah & 0x10) + pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); return __ide_dma_lostirq(drive); } -static void hpt370_clear_engine(ide_drive_t *drive) +static void hpt370_clear_engine (ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - - pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37); + u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50; + pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37); udelay(10); } -static void hpt370_irq_timeout(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u16 bfifo = 0; - u8 dma_cmd; - - pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo); - printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff); - - /* get DMA command mode */ - dma_cmd = hwif->INB(hwif->dma_command); - /* stop DMA */ - hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command); - hpt370_clear_engine(drive); -} - static void hpt370_ide_dma_start(ide_drive_t *drive) { #ifdef HPT_RESET_STATE_ENGINE @@ -807,35 +772,64 @@ static void hpt370_ide_dma_start(ide_drive_t *drive) ide_dma_start(drive); } -static int hpt370_ide_dma_end(ide_drive_t *drive) +static int hpt370_ide_dma_end (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - u8 dma_stat = hwif->INB(hwif->dma_status); + u8 dma_stat = hwif->INB(hwif->dma_status); if (dma_stat & 0x01) { /* wait a little */ udelay(20); dma_stat = hwif->INB(hwif->dma_status); - if (dma_stat & 0x01) - hpt370_irq_timeout(drive); } + if ((dma_stat & 0x01) != 0) + /* fallthrough */ + (void) HWIF(drive)->ide_dma_timeout(drive); + return __ide_dma_end(drive); } -static int hpt370_ide_dma_timeout(ide_drive_t *drive) +static void hpt370_lostirq_timeout (ide_drive_t *drive) { - hpt370_irq_timeout(drive); + ide_hwif_t *hwif = HWIF(drive); + u8 bfifo = 0, reginfo = hwif->channel ? 0x56 : 0x52; + u8 dma_stat = 0, dma_cmd = 0; + + pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo); + printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo); + hpt370_clear_engine(drive); + /* get dma command mode */ + dma_cmd = hwif->INB(hwif->dma_command); + /* stop dma */ + hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command); + dma_stat = hwif->INB(hwif->dma_status); + /* clear errors */ + hwif->OUTB(dma_stat | 0x6, hwif->dma_status); +} + +static int hpt370_ide_dma_timeout (ide_drive_t *drive) +{ + hpt370_lostirq_timeout(drive); + hpt370_clear_engine(drive); return __ide_dma_timeout(drive); } +static int hpt370_ide_dma_lostirq (ide_drive_t *drive) +{ + hpt370_lostirq_timeout(drive); + hpt370_clear_engine(drive); + return __ide_dma_lostirq(drive); +} + /* returns 1 if DMA IRQ issued, 0 otherwise */ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u16 bfifo = 0; - u8 dma_stat; + u8 reginfo = hwif->channel ? 0x56 : 0x52; + u8 dma_stat; - pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo); + pci_read_config_word(hwif->pci_dev, reginfo, &bfifo); if (bfifo & 0x1FF) { // printk("%s: %d bytes in FIFO\n", drive->name, bfifo); return 0; @@ -843,7 +837,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) dma_stat = hwif->INB(hwif->dma_status); /* return 1 if INTR asserted */ - if (dma_stat & 4) + if ((dma_stat & 4) == 4) return 1; if (!drive->waiting_for_dma) @@ -852,17 +846,17 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) return 0; } -static int hpt374_ide_dma_end(ide_drive_t *drive) +static int hpt374_ide_dma_end (ide_drive_t *drive) { + struct pci_dev *dev = HWIF(drive)->pci_dev; ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - u8 mcr = 0, mcr_addr = hwif->select_data; - u8 bwsr = 0, mask = hwif->channel ? 0x02 : 0x01; - - pci_read_config_byte(dev, 0x6a, &bwsr); - pci_read_config_byte(dev, mcr_addr, &mcr); - if (bwsr & mask) - pci_write_config_byte(dev, mcr_addr, mcr | 0x30); + u8 msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50; + u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01; + + pci_read_config_byte(dev, 0x6a, &bwsr_stat); + pci_read_config_byte(dev, mscreg, &msc_stat); + if ((bwsr_stat & bwsr_mask) == bwsr_mask) + pci_write_config_byte(dev, mscreg, msc_stat|0x30); return __ide_dma_end(drive); } @@ -872,37 +866,40 @@ static int hpt374_ide_dma_end(ide_drive_t *drive) * @mode: clocking mode (0x21 for write, 0x23 otherwise) * * Switch the DPLL clock on the HPT3xxN devices. This is a right mess. + * NOTE: avoid touching the disabled primary channel on HPT371N -- it + * doesn't physically exist anyway... */ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) { - u8 scr2 = hwif->INB(hwif->dma_master + 0x7b); + u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b); if ((scr2 & 0x7f) == mode) return; + /* MISC. control register 1 has the channel enable bit... */ + mcr1 = hwif->INB(hwif->dma_master + 0x70); + /* Tristate the bus */ - hwif->OUTB(0x80, hwif->dma_master + 0x73); + if (mcr1 & 0x04) + hwif->OUTB(0x80, hwif->dma_master + 0x73); hwif->OUTB(0x80, hwif->dma_master + 0x77); /* Switch clock and reset channels */ hwif->OUTB(mode, hwif->dma_master + 0x7b); hwif->OUTB(0xc0, hwif->dma_master + 0x79); - /* - * Reset the state machines. - * NOTE: avoid accidentally enabling the disabled channels. - */ - hwif->OUTB(hwif->INB(hwif->dma_master + 0x70) | 0x32, - hwif->dma_master + 0x70); - hwif->OUTB(hwif->INB(hwif->dma_master + 0x74) | 0x32, - hwif->dma_master + 0x74); + /* Reset state machines */ + if (mcr1 & 0x04) + hwif->OUTB(0x37, hwif->dma_master + 0x70); + hwif->OUTB(0x37, hwif->dma_master + 0x74); /* Complete reset */ hwif->OUTB(0x00, hwif->dma_master + 0x79); /* Reconnect channels to bus */ - hwif->OUTB(0x00, hwif->dma_master + 0x73); + if (mcr1 & 0x04) + hwif->OUTB(0x00, hwif->dma_master + 0x73); hwif->OUTB(0x00, hwif->dma_master + 0x77); } @@ -917,12 +914,14 @@ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) { - hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21); + ide_hwif_t *hwif = HWIF(drive); + u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21; + + hpt3xxn_set_clock(hwif, wantclock); } /* * Set/get power state for a drive. - * NOTE: affects both drives on each channel. * * When we turn the power back on, we need to re-initialize things. */ @@ -930,18 +929,26 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) static int hpt3xx_busproc(ide_drive_t *drive, int state) { - ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = drive->hwif; struct pci_dev *dev = hwif->pci_dev; - u8 mcr_addr = hwif->select_data + 2; - u8 resetmask = hwif->channel ? 0x80 : 0x40; - u8 bsr2 = 0; - u16 mcr = 0; + u8 tristate, resetmask, bus_reg = 0; + u16 tri_reg = 0; hwif->bus_state = state; + if (hwif->channel) { + /* secondary channel */ + tristate = 0x56; + resetmask = 0x80; + } else { + /* primary channel */ + tristate = 0x52; + resetmask = 0x40; + } + /* Grab the status. */ - pci_read_config_word(dev, mcr_addr, &mcr); - pci_read_config_byte(dev, 0x59, &bsr2); + pci_read_config_word(dev, tristate, &tri_reg); + pci_read_config_byte(dev, 0x59, &bus_reg); /* * Set the state. We don't set it if we don't need to do so. @@ -949,22 +956,22 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state) */ switch (state) { case BUSSTATE_ON: - if (!(bsr2 & resetmask)) + if (!(bus_reg & resetmask)) return 0; hwif->drives[0].failures = hwif->drives[1].failures = 0; - pci_write_config_byte(dev, 0x59, bsr2 & ~resetmask); - pci_write_config_word(dev, mcr_addr, mcr & ~TRISTATE_BIT); + pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask); + pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT); return 0; case BUSSTATE_OFF: - if ((bsr2 & resetmask) && !(mcr & TRISTATE_BIT)) + if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT)) return 0; - mcr &= ~TRISTATE_BIT; + tri_reg &= ~TRISTATE_BIT; break; case BUSSTATE_TRISTATE: - if ((bsr2 & resetmask) && (mcr & TRISTATE_BIT)) + if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT)) return 0; - mcr |= TRISTATE_BIT; + tri_reg |= TRISTATE_BIT; break; default: return -EINVAL; @@ -973,320 +980,268 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state) hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - pci_write_config_word(dev, mcr_addr, mcr); - pci_write_config_byte(dev, 0x59, bsr2 | resetmask); + pci_write_config_word(dev, tristate, tri_reg); + pci_write_config_byte(dev, 0x59, bus_reg | resetmask); return 0; } -/** - * hpt37x_calibrate_dpll - calibrate the DPLL - * @dev: PCI device - * - * Perform a calibration cycle on the DPLL. - * Returns 1 if this succeeds - */ -static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high) +static void __devinit hpt366_clocking(ide_hwif_t *hwif) { - u32 dpll = (f_high << 16) | f_low | 0x100; - u8 scr2; - int i; + u32 reg1 = 0; + struct hpt_info *info = ide_get_hwifdata(hwif); - pci_write_config_dword(dev, 0x5c, dpll); + pci_read_config_dword(hwif->pci_dev, 0x40, ®1); - /* Wait for oscillator ready */ - for(i = 0; i < 0x5000; ++i) { - udelay(50); - pci_read_config_byte(dev, 0x5b, &scr2); - if (scr2 & 0x80) + /* detect bus speed by looking at control reg timing: */ + switch((reg1 >> 8) & 7) { + case 5: + info->speed = forty_base_hpt36x; + break; + case 9: + info->speed = twenty_five_base_hpt36x; + break; + case 7: + default: + info->speed = thirty_three_base_hpt36x; break; } - /* See if it stays ready (we'll just bail out if it's not yet) */ - for(i = 0; i < 0x1000; ++i) { - pci_read_config_byte(dev, 0x5b, &scr2); - /* DPLL destabilized? */ - if(!(scr2 & 0x80)) - return 0; - } - /* Turn off tuning, we have the DPLL set */ - pci_read_config_dword (dev, 0x5c, &dpll); - pci_write_config_dword(dev, 0x5c, (dpll & ~0x100)); - return 1; } -static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) +static void __devinit hpt37x_clocking(ide_hwif_t *hwif) { - struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); - unsigned long io_base = pci_resource_start(dev, 4); - u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ - enum ata_clock clock; - - if (info == NULL) { - printk(KERN_ERR "%s: out of memory!\n", name); - return -ENOMEM; - } - + struct hpt_info *info = ide_get_hwifdata(hwif); + struct pci_dev *dev = hwif->pci_dev; + int adjust, i; + u16 freq = 0; + u32 pll, temp = 0; + u8 reg5bh = 0, mcr1 = 0; + /* - * Copy everything from a static "template" structure - * to just allocated per-chip hpt_info structure. + * default to pci clock. make sure MA15/16 are set to output + * to prevent drives having problems with 40-pin cables. Needed + * for some drives such as IBM-DTLA which will not enter ready + * state on reset when PDIAG is a input. + * + * ToDo: should we set 0x21 when using PLL mode ? */ - *info = *(struct hpt_info *)pci_get_drvdata(dev); + pci_write_config_byte(dev, 0x5b, 0x23); /* - * FIXME: Not portable. Also, why do we enable the ROM in the first place? - * We don't seem to be using it. + * We'll have to read f_CNT value in order to determine + * the PCI clock frequency according to the following ratio: + * + * f_CNT = Fpci * 192 / Fdpll + * + * First try reading the register in which the HighPoint BIOS + * saves f_CNT value before reprogramming the DPLL from its + * default setting (which differs for the various chips). + * NOTE: This register is only accessible via I/O space. + * + * In case the signature check fails, we'll have to resort to + * reading the f_CNT register itself in hopes that nobody has + * touched the DPLL yet... */ - if (dev->resource[PCI_ROM_RESOURCE].start) - pci_write_config_dword(dev, PCI_ROM_ADDRESS, - dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + temp = inl(pci_resource_start(dev, 4) + 0x90); + if ((temp & 0xFFFFF000) != 0xABCDE000) { + printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n"); + + /* Calculate the average value of f_CNT */ + for (temp = i = 0; i < 128; i++) { + pci_read_config_word(dev, 0x78, &freq); + temp += freq & 0x1ff; + mdelay(1); + } + freq = temp / 128; + } else + freq = temp & 0x1ff; /* - * First, try to estimate the PCI clock frequency... + * HPT3xxN chips use different PCI clock information. + * Currently we always set up the PLL for them. */ - if (info->chip_type >= HPT370) { - u8 scr1 = 0; - u16 f_cnt = 0; - u32 temp = 0; - - /* Interrupt force enable. */ - pci_read_config_byte(dev, 0x5a, &scr1); - if (scr1 & 0x10) - pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); - - /* - * HighPoint does this for HPT372A. - * NOTE: This register is only writeable via I/O space. - */ - if (info->chip_type == HPT372A) - outb(0x0e, io_base + 0x9c); - - /* - * Default to PCI clock. Make sure MA15/16 are set to output - * to prevent drives having problems with 40-pin cables. - */ - pci_write_config_byte(dev, 0x5b, 0x23); - /* - * We'll have to read f_CNT value in order to determine - * the PCI clock frequency according to the following ratio: - * - * f_CNT = Fpci * 192 / Fdpll - * - * First try reading the register in which the HighPoint BIOS - * saves f_CNT value before reprogramming the DPLL from its - * default setting (which differs for the various chips). - * NOTE: This register is only accessible via I/O space. - * - * In case the signature check fails, we'll have to resort to - * reading the f_CNT register itself in hopes that nobody has - * touched the DPLL yet... - */ - temp = inl(io_base + 0x90); - if ((temp & 0xFFFFF000) != 0xABCDE000) { - int i; - - printk(KERN_WARNING "%s: no clock data saved by BIOS\n", - name); - - /* Calculate the average value of f_CNT. */ - for (temp = i = 0; i < 128; i++) { - pci_read_config_word(dev, 0x78, &f_cnt); - temp += f_cnt & 0x1ff; - mdelay(1); - } - f_cnt = temp / 128; - } else - f_cnt = temp & 0x1ff; - - dpll_clk = info->dpll_clk; - pci_clk = (f_cnt * dpll_clk) / 192; - - /* Clamp PCI clock to bands. */ - if (pci_clk < 40) - pci_clk = 33; - else if(pci_clk < 45) - pci_clk = 40; - else if(pci_clk < 55) - pci_clk = 50; + if (info->flags & IS_3xxN) { + if(freq < 0x55) + pll = F_LOW_PCI_33; + else if(freq < 0x70) + pll = F_LOW_PCI_40; + else if(freq < 0x7F) + pll = F_LOW_PCI_50; else - pci_clk = 66; - - printk(KERN_INFO "%s: DPLL base: %d MHz, f_CNT: %d, " - "assuming %d MHz PCI\n", name, dpll_clk, f_cnt, pci_clk); - } else { - u32 itr1 = 0; - - pci_read_config_dword(dev, 0x40, &itr1); + pll = F_LOW_PCI_66; - /* Detect PCI clock by looking at cmd_high_time. */ - switch((itr1 >> 8) & 0x07) { - case 0x09: - pci_clk = 40; - break; - case 0x05: - pci_clk = 25; - break; - case 0x07: - default: - pci_clk = 33; - break; + printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll); + } + else + { + if(freq < 0x9C) + pll = F_LOW_PCI_33; + else if(freq < 0xb0) + pll = F_LOW_PCI_40; + else if(freq <0xc8) + pll = F_LOW_PCI_50; + else + pll = F_LOW_PCI_66; + + if (pll == F_LOW_PCI_33) { + info->speed = thirty_three_base_hpt37x; + printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n"); + } else if (pll == F_LOW_PCI_40) { + /* Unsupported */ + } else if (pll == F_LOW_PCI_50) { + info->speed = fifty_base_hpt37x; + printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n"); + } else { + info->speed = sixty_six_base_hpt37x; + printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); } } - /* Let's assume we'll use PCI clock for the ATA clock... */ - switch (pci_clk) { - case 25: - clock = ATA_CLOCK_25MHZ; - break; - case 33: - default: - clock = ATA_CLOCK_33MHZ; - break; - case 40: - clock = ATA_CLOCK_40MHZ; - break; - case 50: - clock = ATA_CLOCK_50MHZ; - break; - case 66: - clock = ATA_CLOCK_66MHZ; - break; - } + if (pll == F_LOW_PCI_66) + info->flags |= PCI_66MHZ; /* - * Only try the DPLL if we don't have a table for the PCI clock that - * we are running at for HPT370/A, always use it for anything newer... + * only try the pll if we don't have a table for the clock + * speed that we're running at. NOTE: the internal PLL will + * result in slow reads when using a 33MHz PCI clock. we also + * don't like to use the PLL because it will cause glitches + * on PRST/SRST when the HPT state engine gets reset. * - * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI. - * We also don't like using the DPLL because this causes glitches - * on PRST-/SRST- when the state engine gets reset... + * ToDo: Use 66MHz PLL when ATA133 devices are present on a + * 372 device so we can get ATA133 support */ - if (info->chip_type >= HPT374 || info->settings[clock] == NULL) { - u16 f_low, delta = pci_clk < 50 ? 2 : 4; - int adjust; - - /* - * Select 66 MHz DPLL clock only if UltraATA/133 mode is - * supported/enabled, use 50 MHz DPLL clock otherwise... - */ - if (info->max_mode == 0x04) { - dpll_clk = 66; - clock = ATA_CLOCK_66MHZ; - } else if (dpll_clk) { /* HPT36x chips don't have DPLL */ - dpll_clk = 50; - clock = ATA_CLOCK_50MHZ; - } + if (info->speed) + goto init_hpt37X_done; - if (info->settings[clock] == NULL) { - printk(KERN_ERR "%s: unknown bus timing!\n", name); - kfree(info); - return -EIO; + info->flags |= PLL_MODE; + + /* + * Adjust the PLL based upon the PCI clock, enable it, and + * wait for stabilization... + */ + adjust = 0; + freq = (pll < F_LOW_PCI_50) ? 2 : 4; + while (adjust++ < 6) { + pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 | + pll | 0x100); + + /* wait for clock stabilization */ + for (i = 0; i < 0x50000; i++) { + pci_read_config_byte(dev, 0x5b, ®5bh); + if (reg5bh & 0x80) { + /* spin looking for the clock to destabilize */ + for (i = 0; i < 0x1000; ++i) { + pci_read_config_byte(dev, 0x5b, + ®5bh); + if ((reg5bh & 0x80) == 0) + goto pll_recal; + } + pci_read_config_dword(dev, 0x5c, &pll); + pci_write_config_dword(dev, 0x5c, + pll & ~0x100); + pci_write_config_byte(dev, 0x5b, 0x21); + + info->speed = fifty_base_hpt37x; + printk("HPT37X: using 50MHz internal PLL\n"); + goto init_hpt37X_done; + } } +pll_recal: + if (adjust & 1) + pll -= (adjust >> 1); + else + pll += (adjust >> 1); + } - /* Select the DPLL clock. */ - pci_write_config_byte(dev, 0x5b, 0x21); - - /* - * Adjust the DPLL based upon PCI clock, enable it, - * and wait for stabilization... - */ - f_low = (pci_clk * 48) / dpll_clk; - - for (adjust = 0; adjust < 8; adjust++) { - if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta)) - break; +init_hpt37X_done: + if (!info->speed) + printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n", + (info->flags & IS_3xxN) ? "N" : "", pll, freq); + /* + * Reset the state engines. + * NOTE: avoid accidentally enabling the primary channel on HPT371N. + */ + pci_read_config_byte(dev, 0x50, &mcr1); + if (mcr1 & 0x04) + pci_write_config_byte(dev, 0x50, 0x37); + pci_write_config_byte(dev, 0x54, 0x37); + udelay(100); +} - /* - * See if it'll settle at a fractionally different clock - */ - if (adjust & 1) - f_low -= adjust >> 1; - else - f_low += adjust >> 1; - } - if (adjust == 8) { - printk(KERN_ERR "%s: DPLL did not stabilize!\n", name); - kfree(info); - return -EIO; - } +static int __devinit init_hpt37x(struct pci_dev *dev) +{ + u8 reg5ah; - printk("%s: using %d MHz DPLL clock\n", name, dpll_clk); - } else { - /* Mark the fact that we're not using the DPLL. */ - dpll_clk = 0; + pci_read_config_byte(dev, 0x5a, ®5ah); + /* interrupt force enable */ + pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); + return 0; +} - printk("%s: using %d MHz PCI clock\n", name, pci_clk); - } +static int __devinit init_hpt366(struct pci_dev *dev) +{ + u32 reg1 = 0; + u8 drive_fast = 0; /* - * Advance the table pointer to a slot which points to the list - * of the register values settings matching the clock being used. + * Disable the "fast interrupt" prediction. */ - info->settings += clock; - - /* Store the clock frequencies. */ - info->dpll_clk = dpll_clk; - info->pci_clk = pci_clk; - - /* Point to this chip's own instance of the hpt_info structure. */ - pci_set_drvdata(dev, info); - - if (info->chip_type >= HPT370) { - u8 mcr1, mcr4; + pci_read_config_byte(dev, 0x51, &drive_fast); + if (drive_fast & 0x80) + pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); + pci_read_config_dword(dev, 0x40, ®1); + + return 0; +} - /* - * Reset the state engines. - * NOTE: Avoid accidentally enabling the disabled channels. - */ - pci_read_config_byte (dev, 0x50, &mcr1); - pci_read_config_byte (dev, 0x54, &mcr4); - pci_write_config_byte(dev, 0x50, (mcr1 | 0x32)); - pci_write_config_byte(dev, 0x54, (mcr4 | 0x32)); - udelay(100); - } +static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) +{ + int ret = 0; /* - * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in - * the MISC. register to stretch the UltraDMA Tss timing. - * NOTE: This register is only writeable via I/O space. + * FIXME: Not portable. Also, why do we enable the ROM in the first place? + * We don't seem to be using it. */ - if (info->chip_type == HPT371N && clock == ATA_CLOCK_66MHZ) + if (dev->resource[PCI_ROM_RESOURCE].start) + pci_write_config_dword(dev, PCI_ROM_ADDRESS, + dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); + pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); + pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c); + if (hpt_revision(dev) >= 3) + ret = init_hpt37x(dev); + else + ret = init_hpt366(dev); + + if (ret) + return ret; return dev->irq; } static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = pci_get_drvdata(dev); + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata(hwif); + u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02; int serialize = HPT_SERIALIZE_IO; - u8 scr1 = 0, ata66 = (hwif->channel) ? 0x01 : 0x02; - u8 chip_type = info->chip_type; - u8 new_mcr, old_mcr = 0; - - /* Cache the channel's MISC. control registers' offset */ - hwif->select_data = hwif->channel ? 0x54 : 0x50; - + hwif->tuneproc = &hpt3xx_tune_drive; hwif->speedproc = &hpt3xx_tune_chipset; hwif->quirkproc = &hpt3xx_quirkproc; hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; - hwif->busproc = &hpt3xx_busproc; - + /* * HPT3xxN chips have some complications: * * - on 33 MHz PCI we must clock switch * - on 66 MHz PCI we must NOT use the PCI clock */ - if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) { + if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) { /* * Clock is shared between the channels, * so we'll have to serialize them... :-( @@ -1295,171 +1250,200 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->rw_disk = &hpt3xxn_rw_disk; } - /* Serialize access to this device if needed */ - if (serialize && hwif->mate) - hwif->serialized = hwif->mate->serialized = 1; - - /* - * Disable the "fast interrupt" prediction. Don't hold off - * on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr); - - if (info->chip_type >= HPT374) - new_mcr = old_mcr & ~0x07; - else if (info->chip_type >= HPT370) { - new_mcr = old_mcr; - new_mcr &= ~0x02; - -#ifdef HPT_DELAY_INTERRUPT - new_mcr &= ~0x01; -#else - new_mcr |= 0x01; -#endif - } else /* HPT366 and HPT368 */ - new_mcr = old_mcr & ~0x80; - - if (new_mcr != old_mcr) - pci_write_config_byte(dev, hwif->select_data + 1, new_mcr); - - if (!hwif->dma_base) { - hwif->drives[0].autotune = hwif->drives[1].autotune = 1; - return; - } - - hwif->ultra_mask = 0x7f; - hwif->mwdma_mask = 0x07; - /* * The HPT37x uses the CBLID pins as outputs for MA15/MA16 - * address lines to access an external EEPROM. To read valid + * address lines to access an external eeprom. To read valid * cable detect state the pins must be enabled as inputs. */ - if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { + if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) { /* * HPT374 PCI function 1 * - set bit 15 of reg 0x52 to enable TCBLID as input * - set bit 15 of reg 0x56 to enable FCBLID as input */ - u8 mcr_addr = hwif->select_data + 2; - u16 mcr; - - pci_read_config_word (dev, mcr_addr, &mcr); - pci_write_config_word(dev, mcr_addr, (mcr | 0x8000)); + u16 mcr3, mcr6; + pci_read_config_word(dev, 0x52, &mcr3); + pci_read_config_word(dev, 0x56, &mcr6); + pci_write_config_word(dev, 0x52, mcr3 | 0x8000); + pci_write_config_word(dev, 0x56, mcr6 | 0x8000); /* now read cable id register */ - pci_read_config_byte (dev, 0x5a, &scr1); - pci_write_config_word(dev, mcr_addr, mcr); - } else if (chip_type >= HPT370) { + pci_read_config_byte(dev, 0x5a, &ata66); + pci_write_config_word(dev, 0x52, mcr3); + pci_write_config_word(dev, 0x56, mcr6); + } else if (info->revision >= 3) { /* * HPT370/372 and 374 pcifn 0 - * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs + * - clear bit 0 of 0x5b to enable P/SCBLID as inputs */ - u8 scr2 = 0; - - pci_read_config_byte (dev, 0x5b, &scr2); - pci_write_config_byte(dev, 0x5b, (scr2 & ~1)); + u8 scr2; + pci_read_config_byte(dev, 0x5b, &scr2); + pci_write_config_byte(dev, 0x5b, scr2 & ~1); /* now read cable id register */ - pci_read_config_byte (dev, 0x5a, &scr1); - pci_write_config_byte(dev, 0x5b, scr2); - } else - pci_read_config_byte (dev, 0x5a, &scr1); + pci_read_config_byte(dev, 0x5a, &ata66); + pci_write_config_byte(dev, 0x5b, scr2); + } else { + pci_read_config_byte(dev, 0x5a, &ata66); + } - if (!hwif->udma_four) - hwif->udma_four = (scr1 & ata66) ? 0 : 1; +#ifdef DEBUG + printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", + ata66, (ata66 & regmask) ? "33" : "66", + PCI_FUNC(hwif->pci_dev->devfn)); +#endif /* DEBUG */ - hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; + /* Serialize access to this device */ + if (serialize && hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; - if (chip_type >= HPT374) { - hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; - hwif->ide_dma_end = &hpt374_ide_dma_end; - } else if (chip_type >= HPT370) { - hwif->dma_start = &hpt370_ide_dma_start; - hwif->ide_dma_end = &hpt370_ide_dma_end; - hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; - } else - hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; + /* + * Set up ioctl for power status. + * NOTE: power affects both drives on each channel. + */ + hwif->busproc = &hpt3xx_busproc; + + if (!hwif->dma_base) { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + return; + } + + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + + if (!(hwif->udma_four)) + hwif->udma_four = ((ata66 & regmask) ? 0 : 1); + hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; + + if (info->revision >= 8) { + hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; + hwif->ide_dma_end = &hpt374_ide_dma_end; + } else if (info->revision >= 5) { + hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; + hwif->ide_dma_end = &hpt374_ide_dma_end; + } else if (info->revision >= 3) { + hwif->dma_start = &hpt370_ide_dma_start; + hwif->ide_dma_end = &hpt370_ide_dma_end; + hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; + hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; + } else if (info->revision >= 2) + hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; + else + hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; if (!noautodma) hwif->autodma = 1; - hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; } static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) { - struct pci_dev *dev = hwif->pci_dev; - u8 masterdma = 0, slavedma = 0; - u8 dma_new = 0, dma_old = 0; + struct hpt_info *info = ide_get_hwifdata(hwif); + u8 masterdma = 0, slavedma = 0; + u8 dma_new = 0, dma_old = 0; + u8 primary = hwif->channel ? 0x4b : 0x43; + u8 secondary = hwif->channel ? 0x4f : 0x47; unsigned long flags; if (!dmabase) return; - dma_old = hwif->INB(dmabase + 2); + if(info->speed == NULL) { + printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n"); + return; + } + + dma_old = hwif->INB(dmabase+2); local_irq_save(flags); dma_new = dma_old; - pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma); - pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47, &slavedma); + pci_read_config_byte(hwif->pci_dev, primary, &masterdma); + pci_read_config_byte(hwif->pci_dev, secondary, &slavedma); if (masterdma & 0x30) dma_new |= 0x20; - if ( slavedma & 0x30) dma_new |= 0x40; + if (slavedma & 0x30) dma_new |= 0x40; if (dma_new != dma_old) - hwif->OUTB(dma_new, dmabase + 2); + hwif->OUTB(dma_new, dmabase+2); local_irq_restore(flags); ide_setup_dma(hwif, dmabase, 8); } -static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) +/* + * We "borrow" this hook in order to set the data structures + * up early enough before dma or init_hwif calls are made. + */ + +static void __devinit init_iops_hpt366(ide_hwif_t *hwif) { - struct pci_dev *dev2; + struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL); + struct pci_dev *dev = hwif->pci_dev; + u16 did = dev->device; + u8 rid = 0; - if (PCI_FUNC(dev->devfn) & 1) - return -ENODEV; + if(info == NULL) { + printk(KERN_WARNING "hpt366: out of memory.\n"); + return; + } + ide_set_hwifdata(hwif, info); - pci_set_drvdata(dev, &hpt374); + /* Avoid doing the same thing twice. */ + if (hwif->channel && hwif->mate) { + memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info)); + return; + } + + pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid); - if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) { - int ret; + if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) || + ((did == PCI_DEVICE_ID_TTI_HPT372 || + did == PCI_DEVICE_ID_TTI_HPT302 || + did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) || + did == PCI_DEVICE_ID_TTI_HPT372N) + info->flags |= IS_3xxN; + + info->revision = hpt_revision(dev); + + if (info->revision >= 3) + hpt37x_clocking(hwif); + else + hpt366_clocking(hwif); +} - pci_set_drvdata(dev2, &hpt374); +static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *findev = NULL; + + if (PCI_FUNC(dev->devfn) & 1) + return -ENODEV; - if (dev2->irq != dev->irq) { - /* FIXME: we need a core pci_set_interrupt() */ - dev2->irq = dev->irq; - printk(KERN_WARNING "%s: PCI config space interrupt " - "fixed.\n", d->name); + while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + if (findev->irq != dev->irq) { + /* FIXME: we need a core pci_set_interrupt() */ + findev->irq = dev->irq; + printk(KERN_WARNING "%s: pci-config space interrupt " + "fixed.\n", d->name); + } + return ide_setup_pci_devices(dev, findev, d); } - ret = ide_setup_pci_devices(dev, dev2, d); - if (ret < 0) - pci_dev_put(dev2); - return ret; } return ide_setup_pci_device(dev, d); } -static int __devinit init_setup_hpt372n(struct pci_dev *dev, ide_pci_device_t *d) +static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d) { - pci_set_drvdata(dev, &hpt372n); - return ide_setup_pci_device(dev, d); } static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) { - struct hpt_info *info; - u8 rev = 0, mcr1 = 0; - - pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - - if (rev > 1) { - d->name = "HPT371N"; - - info = &hpt371n; - } else - info = &hpt371; + u8 mcr1 = 0; /* * HPT371 chips physically have only one channel, the secondary one, @@ -1469,94 +1453,59 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) */ pci_read_config_byte(dev, 0x50, &mcr1); if (mcr1 & 0x04) - pci_write_config_byte(dev, 0x50, mcr1 & ~0x04); - - pci_set_drvdata(dev, info); - - return ide_setup_pci_device(dev, d); -} - -static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d) -{ - struct hpt_info *info; - u8 rev = 0; - - pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - - if (rev > 1) { - d->name = "HPT372N"; - - info = &hpt372n; - } else - info = &hpt372a; - pci_set_drvdata(dev, info); - - return ide_setup_pci_device(dev, d); -} - -static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d) -{ - struct hpt_info *info; - u8 rev = 0; - - pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - - if (rev > 1) { - d->name = "HPT302N"; - - info = &hpt302n; - } else - info = &hpt302; - pci_set_drvdata(dev, info); + pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04)); return ide_setup_pci_device(dev, d); } static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) { - struct pci_dev *dev2; - u8 rev = 0; - static char *chipset_names[] = { "HPT366", "HPT366", "HPT368", - "HPT370", "HPT370A", "HPT372", - "HPT372N" }; - static struct hpt_info *info[] = { &hpt36x, &hpt36x, &hpt36x, - &hpt370, &hpt370a, &hpt372, - &hpt372n }; + struct pci_dev *findev = NULL; + u8 pin1 = 0, pin2 = 0; + unsigned int class_rev; + char *chipset_names[] = {"HPT366", "HPT366", "HPT368", + "HPT370", "HPT370A", "HPT372", + "HPT372N" }; if (PCI_FUNC(dev->devfn) & 1) return -ENODEV; - pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; - if (rev > 6) - rev = 6; + if(dev->device == PCI_DEVICE_ID_TTI_HPT372N) + class_rev = 6; - d->name = chipset_names[rev]; - - pci_set_drvdata(dev, info[rev]); - - if (rev > 2) - goto init_single; + if(class_rev <= 6) + d->name = chipset_names[class_rev]; + + switch(class_rev) { + case 6: + case 5: + case 4: + case 3: + goto init_single; + default: + break; + } d->channels = 1; - if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) { - u8 pin1 = 0, pin2 = 0; - int ret; - - pci_set_drvdata(dev2, info[rev]); - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - if (pin1 != pin2 && dev->irq == dev2->irq) { - d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", - d->name, pin1, pin2); + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); + while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + pci_read_config_byte(findev, PCI_INTERRUPT_PIN, &pin2); + if ((pin1 != pin2) && (dev->irq == findev->irq)) { + d->bootable = ON_BOARD; + printk("%s: onboard version of chipset, " + "pin1=%d pin2=%d\n", d->name, + pin1, pin2); + } + return ide_setup_pci_devices(dev, findev, d); } - ret = ide_setup_pci_devices(dev, dev2, d); - if (ret < 0) - pci_dev_put(dev2); - return ret; } init_single: return ide_setup_pci_device(dev, d); @@ -1567,68 +1516,64 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT366", .init_setup = init_setup_hpt366, .init_chipset = init_chipset_hpt366, + .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, .extra = 240 },{ /* 1 */ .name = "HPT372A", - .init_setup = init_setup_hpt372a, + .init_setup = init_setup_hpt37x, .init_chipset = init_chipset_hpt366, + .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, - .extra = 240 },{ /* 2 */ .name = "HPT302", - .init_setup = init_setup_hpt302, + .init_setup = init_setup_hpt37x, .init_chipset = init_chipset_hpt366, + .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, - .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, - .extra = 240 },{ /* 3 */ .name = "HPT371", .init_setup = init_setup_hpt371, .init_chipset = init_chipset_hpt366, + .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, - .extra = 240 },{ /* 4 */ .name = "HPT374", .init_setup = init_setup_hpt374, .init_chipset = init_chipset_hpt366, + .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, /* 4 */ .autodma = AUTODMA, - .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, - .extra = 240 },{ /* 5 */ .name = "HPT372N", - .init_setup = init_setup_hpt372n, + .init_setup = init_setup_hpt37x, .init_chipset = init_chipset_hpt366, + .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, /* 4 */ .autodma = AUTODMA, - .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, - .extra = 240 } }; diff --git a/trunk/drivers/ide/pci/it8213.c b/trunk/drivers/ide/pci/it8213.c deleted file mode 100644 index 63248b6909fa..000000000000 --- a/trunk/drivers/ide/pci/it8213.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * ITE 8213 IDE driver - * - * Copyright (C) 2006 Jack Lee - * Copyright (C) 2006 Alan Cox - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * it8213_ratemask - Compute available modes - * @drive: IDE drive - * - * Compute the available speeds for the devices on the interface. This - * is all modes to ATA133 clipped by drive cable setup. - */ - -static u8 it8213_ratemask (ide_drive_t *drive) -{ - u8 mode = 4; - if (!eighty_ninty_three(drive)) - mode = min_t(u8, mode, 1); - return mode; -} - -/** - * it8213_dma_2_pio - return the PIO mode matching DMA - * @xfer_rate: transfer speed - * - * Returns the nearest equivalent PIO timing for the PIO or DMA - * mode requested by the controller. - */ - -static u8 it8213_dma_2_pio (u8 xfer_rate) { - switch(xfer_rate) { - case XFER_UDMA_6: - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - case XFER_MW_DMA_2: - case XFER_PIO_4: - return 4; - case XFER_MW_DMA_1: - case XFER_PIO_3: - return 3; - case XFER_SW_DMA_2: - case XFER_PIO_2: - return 2; - case XFER_MW_DMA_0: - case XFER_SW_DMA_1: - case XFER_SW_DMA_0: - case XFER_PIO_1: - case XFER_PIO_0: - case XFER_PIO_SLOW: - default: - return 0; - } -} - -/* - * it8213_tuneproc - tune a drive - * @drive: drive to tune - * @pio: desired PIO mode - * - * Set the interface PIO mode. - */ - -static void it8213_tuneproc (ide_drive_t *drive, u8 pio) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int is_slave = drive->dn & 1; - int master_port = 0x40; - int slave_port = 0x44; - unsigned long flags; - u16 master_data; - u8 slave_data; - static DEFINE_SPINLOCK(tune_lock); - int control = 0; - - static const u8 timings[][2]= { - { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - - spin_lock_irqsave(&tune_lock, flags); - pci_read_config_word(dev, master_port, &master_data); - - if (pio > 1) - control |= 1; /* Programmable timing on */ - if (drive->media != ide_disk) - control |= 4; /* ATAPI */ - if (pio > 2) - control |= 2; /* IORDY */ - if (is_slave) { - master_data |= 0x4000; - master_data &= ~0x0070; - if (pio > 1) - master_data = master_data | (control << 4); - pci_read_config_byte(dev, slave_port, &slave_data); - slave_data = slave_data & 0xf0; - slave_data = slave_data | (timings[pio][0] << 2) | timings[pio][1]; - } else { - master_data &= ~0x3307; - if (pio > 1) - master_data = master_data | control; - master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); - } - pci_write_config_word(dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(dev, slave_port, slave_data); - spin_unlock_irqrestore(&tune_lock, flags); -} - -/** - * it8213_tune_chipset - set controller timings - * @drive: Drive to set up - * @xferspeed: speed we want to achieve - * - * Tune the ITE chipset for the desired mode. If we can't achieve - * the desired mode then tune for a lower one, but ultimately - * make the thing work. - */ - -static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) -{ - - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - u8 maslave = 0x40; - u8 speed = ide_rate_filter(it8213_ratemask(drive), xferspeed); - int a_speed = 3 << (drive->dn * 4); - int u_flag = 1 << drive->dn; - int v_flag = 0x01 << drive->dn; - int w_flag = 0x10 << drive->dn; - int u_speed = 0; - u16 reg4042, reg4a; - u8 reg48, reg54, reg55; - - pci_read_config_word(dev, maslave, ®4042); - pci_read_config_byte(dev, 0x48, ®48); - pci_read_config_word(dev, 0x4a, ®4a); - pci_read_config_byte(dev, 0x54, ®54); - pci_read_config_byte(dev, 0x55, ®55); - - switch(speed) { - case XFER_UDMA_6: - case XFER_UDMA_4: - case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; - case XFER_UDMA_5: - case XFER_UDMA_3: - case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; - break; - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_SW_DMA_2: - break; - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - break; - default: - return -1; - } - - if (speed >= XFER_UDMA_0) { - if (!(reg48 & u_flag)) - pci_write_config_byte(dev, 0x48, reg48 | u_flag); - if (speed >= XFER_UDMA_5) { - pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); - } else { - pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - } - - if ((reg4a & a_speed) != u_speed) - pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); - if (speed > XFER_UDMA_2) { - if (!(reg54 & v_flag)) - pci_write_config_byte(dev, 0x54, reg54 | v_flag); - } else - pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - } else { - if (reg48 & u_flag) - pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); - if (reg4a & a_speed) - pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - if (reg54 & v_flag) - pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - if (reg55 & w_flag) - pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - } - it8213_tuneproc(drive, it8213_dma_2_pio(speed)); - return ide_config_drive_speed(drive, speed); -} - -/* - * config_chipset_for_dma - configure for DMA - * @drive: drive to configure - * - * Called by the IDE layer when it wants the timings set up. - */ - -static int config_chipset_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_dma_speed(drive, it8213_ratemask(drive)); - - if (!speed) - return 0; - - it8213_tune_chipset(drive, speed); - - return ide_dma_enable(drive); -} - -/** - * it8213_configure_drive_for_dma - set up for DMA transfers - * @drive: drive we are going to set up - * - * Set up the drive for DMA, tune the controller and drive as - * required. If the drive isn't suitable for DMA or we hit - * other problems then we will drop down to PIO and set up - * PIO appropriately - */ - -static int it8213_config_drive_for_dma (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - - hwif->speedproc(drive, XFER_PIO_0 - + ide_get_best_pio_mode(drive, 255, 4, NULL)); - - return hwif->ide_dma_off_quietly(drive); -} - -/** - * init_hwif_it8213 - set up hwif structs - * @hwif: interface to set up - * - * We do the basic set up of the interface structure. The IT8212 - * requires several custom handlers so we override the default - * ide DMA handlers appropriately - */ - -static void __devinit init_hwif_it8213(ide_hwif_t *hwif) -{ - u8 reg42h = 0, ata66 = 0; - - hwif->speedproc = &it8213_tune_chipset; - hwif->tuneproc = &it8213_tuneproc; - - hwif->autodma = 0; - - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - return; - - hwif->atapi_dma = 1; - hwif->ultra_mask = 0x7f; - hwif->mwdma_mask = 0x06; - hwif->swdma_mask = 0x04; - - pci_read_config_byte(hwif->pci_dev, 0x42, ®42h); - ata66 = (reg42h & 0x02) ? 0 : 1; - - hwif->ide_dma_check = &it8213_config_drive_for_dma; - if (!(hwif->udma_four)) - hwif->udma_four = ata66; - - /* - * The BIOS often doesn't set up DMA on this controller - * so we always do it. - */ - if (!noautodma) - hwif->autodma = 1; - - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; -} - - -#define DECLARE_ITE_DEV(name_str) \ - { \ - .name = name_str, \ - .init_hwif = init_hwif_it8213, \ - .channels = 1, \ - .autodma = AUTODMA, \ - .enablebits = {{0x41,0x80,0x80}}, \ - .bootable = ON_BOARD, \ - } - -static ide_pci_device_t it8213_chipsets[] __devinitdata = { - /* 0 */ DECLARE_ITE_DEV("IT8213"), -}; - - -/** - * it8213_init_one - pci layer discovery entry - * @dev: PCI device - * @id: ident table entry - * - * Called by the PCI code when it finds an ITE8213 controller. As - * this device follows the standard interfaces we can use the - * standard helper functions to do almost all the work for us. - */ - -static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]); - return 0; -} - - -static struct pci_device_id it8213_pci_tbl[] = { - { PCI_VENDOR_ID_ITE, 0x8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, it8213_pci_tbl); - -static struct pci_driver driver = { - .name = "ITE8213_IDE", - .id_table = it8213_pci_tbl, - .probe = it8213_init_one, -}; - -static int __init it8213_ide_init(void) -{ - return ide_pci_register_driver(&driver); -} - -module_init(it8213_ide_init); - -MODULE_AUTHOR("Jack Lee, Alan Cox"); -MODULE_DESCRIPTION("PCI driver module for the ITE 8213"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/ide/pci/pdc202xx_new.c b/trunk/drivers/ide/pci/pdc202xx_new.c index 236a03144a27..77a9aaa7dab9 100644 --- a/trunk/drivers/ide/pci/pdc202xx_new.c +++ b/trunk/drivers/ide/pci/pdc202xx_new.c @@ -92,6 +92,26 @@ static u8 pdcnew_ratemask(ide_drive_t *drive) return mode; } +static int check_in_drive_lists(ide_drive_t *drive, const char **list) +{ + struct hd_driveid *id = drive->id; + + if (pdc_quirk_drives == list) { + while (*list) { + if (strstr(id->model, *list++)) { + return 2; + } + } + } else { + while (*list) { + if (!strcmp(*list++,id->model)) { + return 1; + } + } + } + return 0; +} + /** * get_indexed_reg - Get indexed register * @hwif: for the port address @@ -229,6 +249,13 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) return err; } +/* 0 1 2 3 4 5 6 7 8 + * 960, 480, 390, 300, 240, 180, 120, 90, 60 + * 180, 150, 120, 90, 60 + * DMA_Speed + * 180, 120, 90, 90, 90, 60, 30 + * 11, 5, 4, 3, 2, 1, 0 + */ static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) { pio = ide_get_best_pio_mode(drive, pio, 4, NULL); @@ -286,10 +313,12 @@ static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) drive->init_speed = 0; - if ((id->capability & 1) && drive->autodma) { + if (id && (id->capability & 1) && drive->autodma) { - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); + } goto fast_ata_pio; @@ -304,12 +333,21 @@ static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) static int pdcnew_quirkproc(ide_drive_t *drive) { - const char **list, *model = drive->id->model; + return check_in_drive_lists(drive, pdc_quirk_drives); +} - for (list = pdc_quirk_drives; *list != NULL; list++) - if (strstr(model, *list) != NULL) - return 2; - return 0; +static int pdcnew_ide_dma_lostirq(ide_drive_t *drive) +{ + if (HWIF(drive)->resetproc != NULL) + HWIF(drive)->resetproc(drive); + return __ide_dma_lostirq(drive); +} + +static int pdcnew_ide_dma_timeout(ide_drive_t *drive) +{ + if (HWIF(drive)->resetproc != NULL) + HWIF(drive)->resetproc(drive); + return __ide_dma_timeout(drive); } static void pdcnew_reset(ide_drive_t *drive) @@ -561,6 +599,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->err_stops_fifo = 1; hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; + hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; + hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; if (!hwif->udma_four) hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1; diff --git a/trunk/drivers/ide/pci/pdc202xx_old.c b/trunk/drivers/ide/pci/pdc202xx_old.c index 730e8d1ec2f5..143239c093d5 100644 --- a/trunk/drivers/ide/pci/pdc202xx_old.c +++ b/trunk/drivers/ide/pci/pdc202xx_old.c @@ -123,6 +123,26 @@ static u8 pdc202xx_ratemask (ide_drive_t *drive) return mode; } +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + struct hd_driveid *id = drive->id; + + if (pdc_quirk_drives == list) { + while (*list) { + if (strstr(id->model, *list++)) { + return 2; + } + } + } else { + while (*list) { + if (!strcmp(*list++,id->model)) { + return 1; + } + } + } + return 0; +} + static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); @@ -357,12 +377,7 @@ static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive) static int pdc202xx_quirkproc (ide_drive_t *drive) { - const char **list, *model = drive->id->model; - - for (list = pdc_quirk_drives; *list != NULL; list++) - if (strstr(model, *list) != NULL) - return 2; - return 0; + return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); } static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) diff --git a/trunk/drivers/ide/pci/piix.c b/trunk/drivers/ide/pci/piix.c index 52cfc2ac22c1..edb37f3d558d 100644 --- a/trunk/drivers/ide/pci/piix.c +++ b/trunk/drivers/ide/pci/piix.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/piix.c Version 0.46 December 3, 2006 + * linux/drivers/ide/pci/piix.c Version 0.45 May 12, 2006 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick @@ -163,7 +163,7 @@ static u8 piix_ratemask (ide_drive_t *drive) * if the drive cannot see an 80pin cable. */ if (!eighty_ninty_three(drive)) - mode = min_t(u8, mode, 1); + mode = min(mode, (u8)1); return mode; } @@ -216,7 +216,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int is_slave = drive->dn & 1; + int is_slave = (&hwif->drives[1] == drive); int master_port = hwif->channel ? 0x42 : 0x40; int slave_port = 0x44; unsigned long flags; @@ -225,7 +225,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) static DEFINE_SPINLOCK(tune_lock); int control = 0; - /* ISP RTC */ + /* ISP RTC */ static const u8 timings[][2]= { { 0, 0 }, { 0, 0 }, @@ -233,7 +233,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) { 2, 1 }, { 2, 3 }, }; - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); /* * Master vs slave is synchronized above us but the slave register is @@ -243,24 +243,25 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) spin_lock_irqsave(&tune_lock, flags); pci_read_config_word(dev, master_port, &master_data); - if (pio > 1) + if (pio >= 2) control |= 1; /* Programmable timing on */ if (drive->media == ide_disk) control |= 4; /* Prefetch, post write */ - if (pio > 2) + if (pio >= 3) control |= 2; /* IORDY */ if (is_slave) { - master_data |= 0x4000; - master_data &= ~0x0070; + master_data = master_data | 0x4000; if (pio > 1) { /* enable PPE, IE and TIME */ master_data = master_data | (control << 4); + } else { + master_data &= ~0x0070; } pci_read_config_byte(dev, slave_port, &slave_data); slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); } else { - master_data &= ~0x3307; + master_data = master_data & 0xccf8; if (pio > 1) { /* enable PPE, IE and TIME */ master_data = master_data | control; @@ -538,19 +539,13 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { /* 0 */ DECLARE_PIIX_DEV("PIIXa"), /* 1 */ DECLARE_PIIX_DEV("PIIXb"), - /* 2 */ - { /* - * MPIIX actually has only a single IDE channel mapped to - * the primary or secondary ports depending on the value - * of the bit 14 of the IDETIM register at offset 0x6c - */ + { /* 2 */ .name = "MPIIX", .init_hwif = init_hwif_piix, .channels = 2, .autodma = NODMA, - .enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}}, + .enablebits = {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, .bootable = ON_BOARD, - .flags = IDEPCI_FLAG_ISA_PORTS }, /* 3 */ DECLARE_PIIX_DEV("PIIX3"), diff --git a/trunk/drivers/ide/pci/slc90e66.c b/trunk/drivers/ide/pci/slc90e66.c index 2663ddbd9b67..90e79c0844d2 100644 --- a/trunk/drivers/ide/pci/slc90e66.c +++ b/trunk/drivers/ide/pci/slc90e66.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/slc90e66.c Version 0.13 December 30, 2006 + * linux/drivers/ide/pci/slc90e66.c Version 0.12 May 12, 2006 * * Copyright (C) 2000-2002 Andre Hedrick * Copyright (C) 2006 MontaVista Software, Inc. @@ -26,7 +26,7 @@ static u8 slc90e66_ratemask (ide_drive_t *drive) u8 mode = 2; if (!eighty_ninty_three(drive)) - mode = min_t(u8, mode, 1); + mode = min(mode, (u8)1); return mode; } @@ -65,47 +65,36 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int is_slave = drive->dn & 1; + int is_slave = (&hwif->drives[1] == drive); int master_port = hwif->channel ? 0x42 : 0x40; int slave_port = 0x44; unsigned long flags; u16 master_data; u8 slave_data; - int control = 0; - /* ISP RTC */ + /* ISP RTC */ static const u8 timings[][2]= { - { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; + { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); spin_lock_irqsave(&ide_lock, flags); pci_read_config_word(dev, master_port, &master_data); - - if (pio > 1) - control |= 1; /* Programmable timing on */ - if (drive->media == ide_disk) - control |= 4; /* Prefetch, post write */ - if (pio > 2) - control |= 2; /* IORDY */ if (is_slave) { - master_data |= 0x4000; - master_data &= ~0x0070; - if (pio > 1) { + master_data = master_data | 0x4000; + if (pio > 1) /* enable PPE, IE and TIME */ - master_data = master_data | (control << 4); - } + master_data = master_data | 0x0070; pci_read_config_byte(dev, slave_port, &slave_data); slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); } else { - master_data &= ~0x3307; - if (pio > 1) { + master_data = master_data & 0xccf8; + if (pio > 1) /* enable PPE, IE and TIME */ - master_data = master_data | control; - } + master_data = master_data | 0x0007; master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); } pci_write_config_word(dev, master_port, master_data); @@ -184,7 +173,7 @@ static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; - if ((id->capability & 1) && drive->autodma) { + if (id && (id->capability & 1) && drive->autodma) { if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive)) return hwif->ide_dma_on(drive); @@ -212,7 +201,7 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) hwif->irq = hwif->channel ? 15 : 14; hwif->speedproc = &slc90e66_tune_chipset; - hwif->tuneproc = &slc90e66_tune_drive; + hwif->tuneproc = &slc90e66_tune_drive; pci_read_config_byte(hwif->pci_dev, 0x47, ®47); @@ -224,16 +213,14 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) hwif->atapi_dma = 1; hwif->ultra_mask = 0x1f; - hwif->mwdma_mask = 0x06; - hwif->swdma_mask = 0x04; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; - if (!hwif->udma_four) { + if (!(hwif->udma_four)) /* bit[0(1)]: 0:80, 1:40 */ hwif->udma_four = (reg47 & mask) ? 0 : 1; - } hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate; - if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; diff --git a/trunk/drivers/ide/pci/tc86c001.c b/trunk/drivers/ide/pci/tc86c001.c deleted file mode 100644 index 2ad72bbda342..000000000000 --- a/trunk/drivers/ide/pci/tc86c001.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * drivers/ide/pci/tc86c001.c Version 1.00 Dec 12, 2006 - * - * Copyright (C) 2002 Toshiba Corporation - * Copyright (C) 2005-2006 MontaVista Software, Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include - -static inline u8 tc86c001_ratemask(ide_drive_t *drive) -{ - return eighty_ninty_three(drive) ? 2 : 1; -} - -static int tc86c001_tune_chipset(ide_drive_t *drive, u8 speed) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00); - u16 mode, scr = hwif->INW(scr_port); - - speed = ide_rate_filter(tc86c001_ratemask(drive), speed); - - switch (speed) { - case XFER_UDMA_4: mode = 0x00c0; break; - case XFER_UDMA_3: mode = 0x00b0; break; - case XFER_UDMA_2: mode = 0x00a0; break; - case XFER_UDMA_1: mode = 0x0090; break; - case XFER_UDMA_0: mode = 0x0080; break; - case XFER_MW_DMA_2: mode = 0x0070; break; - case XFER_MW_DMA_1: mode = 0x0060; break; - case XFER_MW_DMA_0: mode = 0x0050; break; - case XFER_PIO_4: mode = 0x0400; break; - case XFER_PIO_3: mode = 0x0300; break; - case XFER_PIO_2: mode = 0x0200; break; - case XFER_PIO_1: mode = 0x0100; break; - case XFER_PIO_0: - default: mode = 0x0000; break; - } - - scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f; - scr |= mode; - hwif->OUTW(scr, scr_port); - - return ide_config_drive_speed(drive, speed); -} - -static void tc86c001_tune_drive(ide_drive_t *drive, u8 pio) -{ - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - (void) tc86c001_tune_chipset(drive, XFER_PIO_0 + pio); -} - -/* - * HACKITY HACK - * - * This is a workaround for the limitation 5 of the TC86C001 IDE controller: - * if a DMA transfer terminates prematurely, the controller leaves the device's - * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or - * set the interrupt bit in the DMA status register), thus no PCI interrupt - * will occur until a DMA transfer has been successfully completed. - * - * We work around this by initiating dummy, zero-length DMA transfer on - * a DMA timeout expiration. I found no better way to do this with the current - * IDE core than to temporarily replace a higher level driver's timer expiry - * handler with our own backing up to that handler in case our recovery fails. - */ -static int tc86c001_timer_expiry(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - ide_expiry_t *expiry = ide_get_hwifdata(hwif); - ide_hwgroup_t *hwgroup = HWGROUP(drive); - u8 dma_stat = hwif->INB(hwif->dma_status); - - /* Restore a higher level driver's expiry handler first. */ - hwgroup->expiry = expiry; - - if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */ - unsigned long sc_base = hwif->config_data; - unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); - u8 dma_cmd = hwif->INB(hwif->dma_command); - - printk(KERN_WARNING "%s: DMA interrupt possibly stuck, " - "attempting recovery...\n", drive->name); - - /* Stop DMA */ - hwif->OUTB(dma_cmd & ~0x01, hwif->dma_command); - - /* Setup the dummy DMA transfer */ - hwif->OUTW(0, sc_base + 0x0a); /* Sector Count */ - hwif->OUTW(0, twcr_port); /* Transfer Word Count 1 or 2 */ - - /* Start the dummy DMA transfer */ - hwif->OUTB(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */ - hwif->OUTB(0x01, hwif->dma_command); /* set START_STOPBM */ - - /* - * If an interrupt was pending, it should come thru shortly. - * If not, a higher level driver's expiry handler should - * eventually cause some kind of recovery from the DMA stall. - */ - return WAIT_MIN_SLEEP; - } - - /* Chain to the restored expiry handler if DMA wasn't active. */ - if (likely(expiry != NULL)) - return expiry(drive); - - /* If there was no handler, "emulate" that for ide_timer_expiry()... */ - return -1; -} - -static void tc86c001_dma_start(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned long sc_base = hwif->config_data; - unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); - unsigned long nsectors = hwgroup->rq->nr_sectors; - - /* - * We have to manually load the sector count and size into - * the appropriate system control registers for DMA to work - * with LBA48 and ATAPI devices... - */ - hwif->OUTW(nsectors, sc_base + 0x0a); /* Sector Count */ - hwif->OUTW(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */ - - /* Install our timeout expiry hook, saving the current handler... */ - ide_set_hwifdata(hwif, hwgroup->expiry); - hwgroup->expiry = &tc86c001_timer_expiry; - - ide_dma_start(drive); -} - -static int tc86c001_busproc(ide_drive_t *drive, int state) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long sc_base = hwif->config_data; - u16 scr1; - - /* System Control 1 Register bit 11 (ATA Hard Reset) read */ - scr1 = hwif->INW(sc_base + 0x00); - - switch (state) { - case BUSSTATE_ON: - if (!(scr1 & 0x0800)) - return 0; - scr1 &= ~0x0800; - - hwif->drives[0].failures = hwif->drives[1].failures = 0; - break; - case BUSSTATE_OFF: - if (scr1 & 0x0800) - return 0; - scr1 |= 0x0800; - - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - break; - default: - return -EINVAL; - } - - /* System Control 1 Register bit 11 (ATA Hard Reset) write */ - hwif->OUTW(scr1, sc_base + 0x00); - return 0; -} - -static int config_chipset_for_dma(ide_drive_t *drive) -{ - u8 speed = ide_dma_speed(drive, tc86c001_ratemask(drive)); - - if (!speed) - return 0; - - (void) tc86c001_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - -static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct hd_driveid *id = drive->id; - - if ((id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive) && config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - - goto fast_ata_pio; - - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: - tc86c001_tune_drive(drive, 255); - return hwif->ide_dma_off_quietly(drive); - } - /* IORDY not supported */ - return 0; -} - -static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) -{ - unsigned long sc_base = pci_resource_start(hwif->pci_dev, 5); - u16 scr1 = hwif->INW(sc_base + 0x00);; - - /* System Control 1 Register bit 15 (Soft Reset) set */ - hwif->OUTW(scr1 | 0x8000, sc_base + 0x00); - - /* System Control 1 Register bit 14 (FIFO Reset) set */ - hwif->OUTW(scr1 | 0x4000, sc_base + 0x00); - - /* System Control 1 Register: reset clear */ - hwif->OUTW(scr1 & ~0xc000, sc_base + 0x00); - - /* Store the system control register base for convenience... */ - hwif->config_data = sc_base; - - hwif->tuneproc = &tc86c001_tune_drive; - hwif->speedproc = &tc86c001_tune_chipset; - hwif->busproc = &tc86c001_busproc; - - hwif->drives[0].autotune = hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - return; - - /* - * Sector Count Control Register bits 0 and 1 set: - * software sets Sector Count Register for master and slave device - */ - hwif->OUTW(0x0003, sc_base + 0x0c); - - /* Sector Count Register limit */ - hwif->rqsize = 0xffff; - - hwif->atapi_dma = 1; - hwif->ultra_mask = 0x1f; - hwif->mwdma_mask = 0x07; - - hwif->ide_dma_check = &tc86c001_config_drive_xfer_rate; - hwif->dma_start = &tc86c001_dma_start; - - if (!hwif->udma_four) { - /* - * System Control 1 Register bit 13 (PDIAGN): - * 0=80-pin cable, 1=40-pin cable - */ - scr1 = hwif->INW(sc_base + 0x00); - hwif->udma_four = (scr1 & 0x2000) ? 0 : 1; - } - - if (!noautodma) - hwif->autodma = 1; - hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; -} - -static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev, - const char *name) -{ - int err = pci_request_region(dev, 5, name); - - if (err) - printk(KERN_ERR "%s: system control regs already in use", name); - return err; -} - -static ide_pci_device_t tc86c001_chipset __devinitdata = { - .name = "TC86C001", - .init_chipset = init_chipset_tc86c001, - .init_hwif = init_hwif_tc86c001, - .channels = 1, - .autodma = AUTODMA, - .bootable = OFF_BOARD -}; - -static int __devinit tc86c001_init_one(struct pci_dev *dev, - const struct pci_device_id *id) -{ - return ide_setup_pci_device(dev, &tc86c001_chipset); -} - -static struct pci_device_id tc86c001_pci_tbl[] = { - { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl); - -static struct pci_driver driver = { - .name = "TC86C001", - .id_table = tc86c001_pci_tbl, - .probe = tc86c001_init_one -}; - -static int __init tc86c001_ide_init(void) -{ - return ide_pci_register_driver(&driver); -} -module_init(tc86c001_ide_init); - -MODULE_AUTHOR("MontaVista Software, Inc. "); -MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/ide/setup-pci.c b/trunk/drivers/ide/setup-pci.c index a52c80fe7d3e..695e23904d30 100644 --- a/trunk/drivers/ide/setup-pci.c +++ b/trunk/drivers/ide/setup-pci.c @@ -783,11 +783,10 @@ static LIST_HEAD(ide_pci_drivers); * Returns are the same as for pci_register_driver */ -int __ide_pci_register_driver(struct pci_driver *driver, struct module *module, - const char *mod_name) +int __ide_pci_register_driver(struct pci_driver *driver, struct module *module) { if(!pre_init) - return __pci_register_driver(driver, module, mod_name); + return __pci_register_driver(driver, module); driver->driver.owner = module; list_add_tail(&driver->node, &ide_pci_drivers); return 0; @@ -863,6 +862,6 @@ void __init ide_scan_pcibus (int scan_direction) { list_del(l); d = list_entry(l, struct pci_driver, node); - __pci_register_driver(d, d->driver.owner, d->driver.mod_name); + __pci_register_driver(d, d->driver.owner); } } diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c index af5ee2ec4499..705eb1d0e554 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -958,17 +958,16 @@ struct ipoib_dev_priv *ipoib_intf_alloc(const char *name) return netdev_priv(dev); } -static ssize_t show_pkey(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_pkey(struct class_device *cdev, char *buf) { - struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); + struct ipoib_dev_priv *priv = + netdev_priv(container_of(cdev, struct net_device, class_dev)); return sprintf(buf, "0x%04x\n", priv->pkey); } -static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); +static CLASS_DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); -static ssize_t create_child(struct device *dev, - struct device_attribute *attr, +static ssize_t create_child(struct class_device *cdev, const char *buf, size_t count) { int pkey; @@ -986,14 +985,14 @@ static ssize_t create_child(struct device *dev, */ pkey |= 0x8000; - ret = ipoib_vlan_add(to_net_dev(dev), pkey); + ret = ipoib_vlan_add(container_of(cdev, struct net_device, class_dev), + pkey); return ret ? ret : count; } -static DEVICE_ATTR(create_child, S_IWUGO, NULL, create_child); +static CLASS_DEVICE_ATTR(create_child, S_IWUGO, NULL, create_child); -static ssize_t delete_child(struct device *dev, - struct device_attribute *attr, +static ssize_t delete_child(struct class_device *cdev, const char *buf, size_t count) { int pkey; @@ -1005,16 +1004,18 @@ static ssize_t delete_child(struct device *dev, if (pkey < 0 || pkey > 0xffff) return -EINVAL; - ret = ipoib_vlan_delete(to_net_dev(dev), pkey); + ret = ipoib_vlan_delete(container_of(cdev, struct net_device, class_dev), + pkey); return ret ? ret : count; } -static DEVICE_ATTR(delete_child, S_IWUGO, NULL, delete_child); +static CLASS_DEVICE_ATTR(delete_child, S_IWUGO, NULL, delete_child); int ipoib_add_pkey_attr(struct net_device *dev) { - return device_create_file(&dev->dev, &dev_attr_pkey); + return class_device_create_file(&dev->class_dev, + &class_device_attr_pkey); } static struct net_device *ipoib_add_port(const char *format, @@ -1082,9 +1083,11 @@ static struct net_device *ipoib_add_port(const char *format, if (ipoib_add_pkey_attr(priv->dev)) goto sysfs_failed; - if (device_create_file(&priv->dev->dev, &dev_attr_create_child)) + if (class_device_create_file(&priv->dev->class_dev, + &class_device_attr_create_child)) goto sysfs_failed; - if (device_create_file(&priv->dev->dev, &dev_attr_delete_child)) + if (class_device_create_file(&priv->dev->class_dev, + &class_device_attr_delete_child)) goto sysfs_failed; return priv->dev; diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 085eafe6667c..f887780e8093 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -42,15 +42,15 @@ #include "ipoib.h" -static ssize_t show_parent(struct device *d, struct device_attribute *attr, - char *buf) +static ssize_t show_parent(struct class_device *class_dev, char *buf) { - struct net_device *dev = to_net_dev(d); + struct net_device *dev = + container_of(class_dev, struct net_device, class_dev); struct ipoib_dev_priv *priv = netdev_priv(dev); return sprintf(buf, "%s\n", priv->parent->name); } -static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL); +static CLASS_DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL); int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) { @@ -118,7 +118,8 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) if (ipoib_add_pkey_attr(priv->dev)) goto sysfs_failed; - if (device_create_file(&priv->dev->dev, &dev_attr_parent)) + if (class_device_create_file(&priv->dev->class_dev, + &class_device_attr_parent)) goto sysfs_failed; list_add_tail(&priv->list, &ppriv->child_intfs); diff --git a/trunk/drivers/input/serio/serio.c b/trunk/drivers/input/serio/serio.c index 17c8c63cbe1a..f0ce822c1028 100644 --- a/trunk/drivers/input/serio/serio.c +++ b/trunk/drivers/input/serio/serio.c @@ -45,7 +45,7 @@ EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(__serio_register_port); EXPORT_SYMBOL(serio_unregister_port); EXPORT_SYMBOL(serio_unregister_child_port); -EXPORT_SYMBOL(__serio_register_driver); +EXPORT_SYMBOL(serio_register_driver); EXPORT_SYMBOL(serio_unregister_driver); EXPORT_SYMBOL(serio_open); EXPORT_SYMBOL(serio_close); @@ -789,14 +789,12 @@ static void serio_attach_driver(struct serio_driver *drv) drv->driver.name, error); } -int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name) +int serio_register_driver(struct serio_driver *drv) { int manual_bind = drv->manual_bind; int error; drv->driver.bus = &serio_bus; - drv->driver.owner = owner; - drv->driver.mod_name = mod_name; /* * Temporarily disable automatic binding because probing diff --git a/trunk/drivers/media/video/zc0301/zc0301_sensor.h b/trunk/drivers/media/video/zc0301/zc0301_sensor.h index 3daf049a288a..4363a915b1f4 100644 --- a/trunk/drivers/media/video/zc0301/zc0301_sensor.h +++ b/trunk/drivers/media/video/zc0301/zc0301_sensor.h @@ -75,6 +75,7 @@ static const struct usb_device_id zc0301_id_table[] = { \ { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */ \ { ZC0301_USB_DEVICE(0x055f, 0xd004, 0xff), }, /* TAS5130 */ \ + { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ { ZC0301_USB_DEVICE(0x0ac8, 0x301b, 0xff), }, /* PB-0330/HV7131 */ \ { ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */ \ diff --git a/trunk/drivers/net/3c59x.c b/trunk/drivers/net/3c59x.c index 716a47210aa3..80bdcf846234 100644 --- a/trunk/drivers/net/3c59x.c +++ b/trunk/drivers/net/3c59x.c @@ -792,7 +792,8 @@ static void poll_vortex(struct net_device *dev) { struct vortex_private *vp = netdev_priv(dev); unsigned long flags; - local_irq_save(flags); + local_save_flags(flags); + local_irq_disable(); (vp->full_bus_master_rx ? boomerang_interrupt:vortex_interrupt)(dev->irq,dev); local_irq_restore(flags); } diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index ad92b6a76ee6..8aa8dd02b910 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -190,7 +190,7 @@ config MII config MACB tristate "Atmel MACB support" - depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263) + depends on NET_ETHERNET && AVR32 select MII help The Atmel MACB ethernet interface is found on many AT32 and AT91 @@ -235,6 +235,16 @@ config BMAC To compile this driver as a module, choose M here: the module will be called bmac. +config OAKNET + tristate "National DP83902AV (Oak ethernet) support" + depends on NET_ETHERNET && PPC && BROKEN + select CRC32 + help + Say Y if your machine has this type of Ethernet network card. + + To compile this driver as a module, choose M here: the module + will be called oaknet. + config ARIADNE tristate "Ariadne support" depends on NET_ETHERNET && ZORRO @@ -1145,6 +1155,21 @@ config SEEQ8005 . The module will be called seeq8005. +config SKMC + tristate "SKnet MCA support" + depends on NET_ETHERNET && MCA && BROKEN + ---help--- + These are Micro Channel Ethernet adapters. You need to say Y to "MCA + support" in order to use this driver. Supported cards are the SKnet + Junior MC2 and the SKnet MC2(+). The driver automatically + distinguishes between the two cards. Note that using multiple boards + of different type hasn't been tested with this driver. Say Y if you + have one of these Ethernet adapters. + + To compile this driver as a module, choose M here and read + . The module + will be called sk_mca. + config NE2_MCA tristate "NE/2 (ne2000 MCA version) support" depends on NET_ETHERNET && MCA_LEGACY @@ -1763,18 +1788,6 @@ config LAN_SAA9730 workstations. See . -config SC92031 - tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)" - depends on NET_PCI && PCI && EXPERIMENTAL - select CRC32 - ---help--- - This is a driver for the Fast Ethernet PCI network cards based on - the Silan SC92031 chip (sometimes also called Rsltek 8139D). If you - have one of these, say Y here. - - To compile this driver as a module, choose M here: the module - will be called sc92031. This is recommended. - config NET_POCKET bool "Pocket and portable adapters" depends on NET_ETHERNET && PARPORT @@ -2379,24 +2392,6 @@ config CHELSIO_T1_NAPI NAPI is a driver API designed to reduce CPU and interrupt load when the driver is receiving lots of packets from the card. -config CHELSIO_T3 - tristate "Chelsio Communications T3 10Gb Ethernet support" - depends on PCI - help - This driver supports Chelsio T3-based gigabit and 10Gb Ethernet - adapters. - - For general information about Chelsio and our products, visit - our website at . - - For customer support, please visit our customer support page at - . - - Please send feedback to . - - To compile this driver as a module, choose M here: the module - will be called cxgb3. - config EHEA tristate "eHEA Ethernet support" depends on IBMEBUS @@ -2493,13 +2488,6 @@ config NETXEN_NIC help This enables the support for NetXen's Gigabit Ethernet card. -config PASEMI_MAC - tristate "PA Semi 1/10Gbit MAC" - depends on PPC64 && PCI - help - This driver supports the on-chip 1/10Gbit Ethernet controller on - PA Semi's PWRficient line of chips. - endmenu source "drivers/net/tokenring/Kconfig" @@ -2553,7 +2541,6 @@ config DEFXX config SKFP tristate "SysKonnect FDDI PCI support" depends on FDDI && PCI - select BITREVERSE ---help--- Say Y here if you have a SysKonnect FDDI PCI adapter. The following adapters are supported by this driver: diff --git a/trunk/drivers/net/Makefile b/trunk/drivers/net/Makefile index 0878e3df5174..4c0d4e5ce42b 100644 --- a/trunk/drivers/net/Makefile +++ b/trunk/drivers/net/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_IBM_EMAC) += ibm_emac/ obj-$(CONFIG_IXGB) += ixgb/ obj-$(CONFIG_CHELSIO_T1) += chelsio/ -obj-$(CONFIG_CHELSIO_T3) += cxgb3/ obj-$(CONFIG_EHEA) += ehea/ obj-$(CONFIG_BONDING) += bonding/ obj-$(CONFIG_GIANFAR) += gianfar_driver.o @@ -37,6 +36,8 @@ obj-$(CONFIG_CASSINI) += cassini.o obj-$(CONFIG_MACE) += mace.o obj-$(CONFIG_BMAC) += bmac.o +obj-$(CONFIG_OAKNET) += oaknet.o 8390.o + obj-$(CONFIG_DGRS) += dgrs.o obj-$(CONFIG_VORTEX) += 3c59x.o obj-$(CONFIG_TYPHOON) += typhoon.o @@ -136,6 +137,7 @@ obj-$(CONFIG_AT1700) += at1700.o obj-$(CONFIG_EL1) += 3c501.o obj-$(CONFIG_EL16) += 3c507.o obj-$(CONFIG_ELMC) += 3c523.o +obj-$(CONFIG_SKMC) += sk_mca.o obj-$(CONFIG_IBMLANA) += ibmlana.o obj-$(CONFIG_ELMC_II) += 3c527.o obj-$(CONFIG_EL3) += 3c509.o @@ -158,7 +160,6 @@ obj-$(CONFIG_APRICOT) += 82596.o obj-$(CONFIG_LASI_82596) += lasi_82596.o obj-$(CONFIG_MVME16x_NET) += 82596.o obj-$(CONFIG_BVME6000_NET) += 82596.o -obj-$(CONFIG_SC92031) += sc92031.o # This is also a 82596 and should probably be merged obj-$(CONFIG_LP486E) += lp486e.o @@ -195,7 +196,6 @@ obj-$(CONFIG_SMC91X) += smc91x.o obj-$(CONFIG_SMC911X) += smc911x.o obj-$(CONFIG_DM9000) += dm9000.o obj-$(CONFIG_FEC_8XX) += fec_8xx/ -obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o obj-$(CONFIG_MACB) += macb.o diff --git a/trunk/drivers/net/Space.c b/trunk/drivers/net/Space.c index dd8ed456c8b2..9305eb9b1b98 100644 --- a/trunk/drivers/net/Space.c +++ b/trunk/drivers/net/Space.c @@ -59,6 +59,7 @@ extern struct net_device *wavelan_probe(int unit); extern struct net_device *arlan_probe(int unit); extern struct net_device *el16_probe(int unit); extern struct net_device *elmc_probe(int unit); +extern struct net_device *skmca_probe(int unit); extern struct net_device *elplus_probe(int unit); extern struct net_device *ac3200_probe(int unit); extern struct net_device *es_probe(int unit); @@ -151,6 +152,9 @@ static struct devprobe2 mca_probes[] __initdata = { #endif #ifdef CONFIG_ELMC_II /* 3c527 */ {mc32_probe, 0}, +#endif +#ifdef CONFIG_SKMC /* SKnet Microchannel */ + {skmca_probe, 0}, #endif {NULL, 0}, }; diff --git a/trunk/drivers/net/amd8111e.c b/trunk/drivers/net/amd8111e.c index 9c399aaefbdd..18896f24d407 100644 --- a/trunk/drivers/net/amd8111e.c +++ b/trunk/drivers/net/amd8111e.c @@ -1334,7 +1334,8 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id) static void amd8111e_poll(struct net_device *dev) { unsigned long flags; - local_irq_save(flags); + local_save_flags(flags); + local_irq_disable(); amd8111e_interrupt(0, dev); local_irq_restore(flags); } diff --git a/trunk/drivers/net/arm/at91_ether.c b/trunk/drivers/net/arm/at91_ether.c index 1621b8fe35cf..fada15d959de 100644 --- a/trunk/drivers/net/arm/at91_ether.c +++ b/trunk/drivers/net/arm/at91_ether.c @@ -641,7 +641,7 @@ static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo { strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strlcpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); } static const struct ethtool_ops at91ether_ethtool_ops = { diff --git a/trunk/drivers/net/arm/etherh.c b/trunk/drivers/net/arm/etherh.c index 72c41f5907f2..f3faa4fe58e7 100644 --- a/trunk/drivers/net/arm/etherh.c +++ b/trunk/drivers/net/arm/etherh.c @@ -587,7 +587,7 @@ static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i { strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, dev->dev.parent->bus_id, + strlcpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); } diff --git a/trunk/drivers/net/b44.c b/trunk/drivers/net/b44.c index 5ff7882297d6..303a8d94ad4b 100644 --- a/trunk/drivers/net/b44.c +++ b/trunk/drivers/net/b44.c @@ -721,7 +721,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) struct ring_info *src_map, *dest_map; struct rx_header *rh; int dest_idx; - __le32 ctrl; + u32 ctrl; dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1); dest_desc = &bp->rx_ring[dest_idx]; @@ -783,7 +783,7 @@ static int b44_rx(struct b44 *bp, int budget) RX_PKT_BUF_SZ, PCI_DMA_FROMDEVICE); rh = (struct rx_header *) skb->data; - len = le16_to_cpu(rh->len); + len = cpu_to_le16(rh->len); if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) || (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) { drop_it: @@ -799,7 +799,7 @@ static int b44_rx(struct b44 *bp, int budget) do { udelay(2); barrier(); - len = le16_to_cpu(rh->len); + len = cpu_to_le16(rh->len); } while (len == 0 && i++ < 5); if (len == 0) goto drop_it; @@ -2061,7 +2061,7 @@ static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int b44_read_eeprom(struct b44 *bp, u8 *data) { long i; - __le16 *ptr = (__le16 *) data; + u16 *ptr = (u16 *) data; for (i = 0; i < 128; i += 2) ptr[i / 2] = cpu_to_le16(readw(bp->regs + 4096 + i)); diff --git a/trunk/drivers/net/b44.h b/trunk/drivers/net/b44.h index 18fc13336628..4944507fad23 100644 --- a/trunk/drivers/net/b44.h +++ b/trunk/drivers/net/b44.h @@ -308,8 +308,8 @@ #define MII_TLEDCTRL_ENABLE 0x0040 struct dma_desc { - __le32 ctrl; - __le32 addr; + u32 ctrl; + u32 addr; }; /* There are only 12 bits in the DMA engine for descriptor offsetting @@ -327,9 +327,9 @@ struct dma_desc { #define RX_COPY_THRESHOLD 256 struct rx_header { - __le16 len; - __le16 flags; - __le16 pad[12]; + u16 len; + u16 flags; + u16 pad[12]; }; #define RX_HEADER_LEN 28 diff --git a/trunk/drivers/net/bmac.c b/trunk/drivers/net/bmac.c index c143304dcff5..4528ce9c4e43 100644 --- a/trunk/drivers/net/bmac.c +++ b/trunk/drivers/net/bmac.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -141,6 +140,7 @@ static unsigned char *bmac_emergency_rxbuf; + (N_RX_RING + N_TX_RING + 4) * sizeof(struct dbdma_cmd) \ + sizeof(struct sk_buff_head)) +static unsigned char bitrev(unsigned char b); static int bmac_open(struct net_device *dev); static int bmac_close(struct net_device *dev); static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev); @@ -586,6 +586,18 @@ bmac_construct_rxbuff(struct sk_buff *skb, volatile struct dbdma_cmd *cp) virt_to_bus(addr), 0); } +/* Bit-reverse one byte of an ethernet hardware address. */ +static unsigned char +bitrev(unsigned char b) +{ + int d = 0, i; + + for (i = 0; i < 8; ++i, b >>= 1) + d = (d << 1) | (b & 1); + return d; +} + + static void bmac_init_tx_ring(struct bmac_data *bp) { @@ -1212,8 +1224,8 @@ bmac_get_station_address(struct net_device *dev, unsigned char *ea) { reset_and_select_srom(dev); data = read_srom(dev, i + EnetAddressOffset/2, SROMAddressBits); - ea[2*i] = bitrev8(data & 0x0ff); - ea[2*i+1] = bitrev8((data >> 8) & 0x0ff); + ea[2*i] = bitrev(data & 0x0ff); + ea[2*i+1] = bitrev((data >> 8) & 0x0ff); } } @@ -1303,7 +1315,7 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i rev = addr[0] == 0 && addr[1] == 0xA0; for (j = 0; j < 6; ++j) - dev->dev_addr[j] = rev ? bitrev8(addr[j]): addr[j]; + dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j]; /* Enable chip without interrupts for now */ bmac_enable_and_reset_chip(dev); diff --git a/trunk/drivers/net/bnx2.c b/trunk/drivers/net/bnx2.c index 5a96d7611af1..ee7b75b976b5 100644 --- a/trunk/drivers/net/bnx2.c +++ b/trunk/drivers/net/bnx2.c @@ -39,9 +39,12 @@ #include #define BCM_VLAN 1 #endif +#ifdef NETIF_F_TSO #include #include #include +#define BCM_TSO 1 +#endif #include #include #include @@ -1725,7 +1728,7 @@ bnx2_tx_int(struct bnx2 *bp) tx_buf = &bp->tx_buf_ring[sw_ring_cons]; skb = tx_buf->skb; - +#ifdef BCM_TSO /* partial BD completions possible with TSO packets */ if (skb_is_gso(skb)) { u16 last_idx, last_ring_idx; @@ -1741,7 +1744,7 @@ bnx2_tx_int(struct bnx2 *bp) break; } } - +#endif pci_unmap_single(bp->pdev, pci_unmap_addr(tx_buf, mapping), skb_headlen(skb), PCI_DMA_TODEVICE); @@ -4511,6 +4514,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); } +#ifdef BCM_TSO if ((mss = skb_shinfo(skb)->gso_size) && (skb->len > (bp->dev->mtu + ETH_HLEN))) { u32 tcp_opt_len, ip_tcp_len; @@ -4543,6 +4547,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) } } else +#endif { mss = 0; } @@ -5539,8 +5544,10 @@ static const struct ethtool_ops bnx2_ethtool_ops = { .set_tx_csum = ethtool_op_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, +#ifdef BCM_TSO .get_tso = ethtool_op_get_tso, .set_tso = bnx2_set_tso, +#endif .self_test_count = bnx2_self_test_count, .self_test = bnx2_self_test, .get_strings = bnx2_get_strings, @@ -5947,7 +5954,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) * responding after a while. * * AMD believes this incompatibility is unique to the 5706, and - * prefers to locally disable MSI rather than globally disabling it. + * prefers to locally disable MSI rather than globally disabling it + * using pci_msi_quirk. */ if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) { struct pci_dev *amd_8132 = NULL; @@ -6096,7 +6104,9 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef BCM_VLAN dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; #endif +#ifdef BCM_TSO dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; +#endif netif_carrier_off(bp->dev); diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index d3801a00d3d5..6482aed4bb7c 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -4704,7 +4704,6 @@ static int bond_check_params(struct bond_params *params) static struct lock_class_key bonding_netdev_xmit_lock_key; /* Create a new bond based on the specified name and bonding parameters. - * If name is NULL, obtain a suitable "bond%d" name for us. * Caller must NOT hold rtnl_lock; we need to release it here before we * set up our sysfs entries. */ @@ -4714,8 +4713,7 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond int res; rtnl_lock(); - bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "", - ether_setup); + bond_dev = alloc_netdev(sizeof(struct bonding), name, ether_setup); if (!bond_dev) { printk(KERN_ERR DRV_NAME ": %s: eek! can't alloc netdev!\n", @@ -4724,12 +4722,6 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond goto out_rtnl; } - if (!name) { - res = dev_alloc_name(bond_dev, "bond%d"); - if (res < 0) - goto out_netdev; - } - /* bond_init() must be called after dev_alloc_name() (for the * /proc files), but before register_netdevice(), because we * need to set function pointers. @@ -4756,19 +4748,14 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond rtnl_unlock(); /* allows sysfs registration of net device */ res = bond_create_sysfs_entry(bond_dev->priv); - if (res < 0) { - rtnl_lock(); - goto out_bond; - } - - return 0; - + goto done; out_bond: bond_deinit(bond_dev); out_netdev: free_netdev(bond_dev); out_rtnl: rtnl_unlock(); +done: return res; } @@ -4776,6 +4763,7 @@ static int __init bonding_init(void) { int i; int res; + char new_bond_name[8]; /* Enough room for 999 bonds at init. */ printk(KERN_INFO "%s", version); @@ -4788,7 +4776,8 @@ static int __init bonding_init(void) bond_create_proc_dir(); #endif for (i = 0; i < max_bonds; i++) { - res = bond_create(NULL, &bonding_defaults, NULL); + sprintf(new_bond_name, "bond%d",i); + res = bond_create(new_bond_name,&bonding_defaults, NULL); if (res) goto err; } diff --git a/trunk/drivers/net/bonding/bond_sysfs.c b/trunk/drivers/net/bonding/bond_sysfs.c index 878f7aabeeac..ced9ed8f995a 100644 --- a/trunk/drivers/net/bonding/bond_sysfs.c +++ b/trunk/drivers/net/bonding/bond_sysfs.c @@ -39,7 +39,8 @@ /* #define BONDING_DEBUG 1 */ #include "bonding.h" -#define to_dev(obj) container_of(obj,struct device,kobj) +#define to_class_dev(obj) container_of(obj,struct class_device,kobj) +#define to_net_dev(class) container_of(class, struct net_device, class_dev) #define to_bond(cd) ((struct bonding *)(to_net_dev(cd)->priv)) /*---------------------------- Declarations -------------------------------*/ @@ -153,7 +154,7 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t * If it's > expected, then there's a file open, * and we have to fail. */ - if (atomic_read(&bond->dev->dev.kobj.kref.refcount) + if (atomic_read(&bond->dev->class_dev.kobj.kref.refcount) > expected_refcount){ rtnl_unlock(); printk(KERN_INFO DRV_NAME @@ -200,13 +201,13 @@ int bond_create_slave_symlinks(struct net_device *master, struct net_device *sla int ret = 0; /* first, create a link from the slave back to the master */ - ret = sysfs_create_link(&(slave->dev.kobj), &(master->dev.kobj), + ret = sysfs_create_link(&(slave->class_dev.kobj), &(master->class_dev.kobj), "master"); if (ret) return ret; /* next, create a link from the master to the slave */ sprintf(linkname,"slave_%s",slave->name); - ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj), + ret = sysfs_create_link(&(master->class_dev.kobj), &(slave->class_dev.kobj), linkname); return ret; @@ -216,21 +217,20 @@ void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *s { char linkname[IFNAMSIZ+7]; - sysfs_remove_link(&(slave->dev.kobj), "master"); + sysfs_remove_link(&(slave->class_dev.kobj), "master"); sprintf(linkname,"slave_%s",slave->name); - sysfs_remove_link(&(master->dev.kobj), linkname); + sysfs_remove_link(&(master->class_dev.kobj), linkname); } /* * Show the slaves in the current bond. */ -static ssize_t bonding_show_slaves(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t bonding_show_slaves(struct class_device *cd, char *buf) { struct slave *slave; int i, res = 0; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); read_lock_bh(&bond->lock); bond_for_each_slave(bond, slave, i) { @@ -254,16 +254,14 @@ static ssize_t bonding_show_slaves(struct device *d, * up for this to succeed. * This function is largely the same flow as bonding_update_bonds(). */ -static ssize_t bonding_store_slaves(struct device *d, - struct device_attribute *attr, - const char *buffer, size_t count) +static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer, size_t count) { char command[IFNAMSIZ + 1] = { 0, }; char *ifname; int i, res, found, ret = count; struct slave *slave; struct net_device *dev = NULL; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); /* Quick sanity check -- is the bond interface up? */ if (!(bond->dev->flags & IFF_UP)) { @@ -389,28 +387,25 @@ static ssize_t bonding_store_slaves(struct device *d, return ret; } -static DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves); +static CLASS_DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves); /* * Show and set the bonding mode. The bond interface must be down to * change the mode. */ -static ssize_t bonding_show_mode(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t bonding_show_mode(struct class_device *cd, char *buf) { - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); return sprintf(buf, "%s %d\n", bond_mode_tbl[bond->params.mode].modename, bond->params.mode) + 1; } -static ssize_t bonding_store_mode(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size_t count) { int new_value, ret = count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (bond->dev->flags & IFF_UP) { printk(KERN_ERR DRV_NAME @@ -443,18 +438,16 @@ static ssize_t bonding_store_mode(struct device *d, out: return ret; } -static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode); +static CLASS_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode); /* * Show and set the bonding transmit hash method. The bond interface must be down to * change the xmit hash policy. */ -static ssize_t bonding_show_xmit_hash(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_xmit_hash(struct class_device *cd, char *buf) { int count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if ((bond->params.mode != BOND_MODE_XOR) && (bond->params.mode != BOND_MODE_8023AD)) { @@ -469,12 +462,10 @@ static ssize_t bonding_show_xmit_hash(struct device *d, return count; } -static ssize_t bonding_store_xmit_hash(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_xmit_hash(struct class_device *cd, const char *buf, size_t count) { int new_value, ret = count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (bond->dev->flags & IFF_UP) { printk(KERN_ERR DRV_NAME @@ -510,28 +501,24 @@ static ssize_t bonding_store_xmit_hash(struct device *d, out: return ret; } -static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash); +static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash); /* * Show and set arp_validate. */ -static ssize_t bonding_show_arp_validate(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_arp_validate(struct class_device *cd, char *buf) { - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); return sprintf(buf, "%s %d\n", arp_validate_tbl[bond->params.arp_validate].modename, bond->params.arp_validate) + 1; } -static ssize_t bonding_store_arp_validate(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_arp_validate(struct class_device *cd, const char *buf, size_t count) { int new_value; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); new_value = bond_parse_parm((char *)buf, arp_validate_tbl); if (new_value < 0) { @@ -561,7 +548,7 @@ static ssize_t bonding_store_arp_validate(struct device *d, return count; } -static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); +static CLASS_DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); /* * Show and set the arp timer interval. There are two tricky bits @@ -569,21 +556,17 @@ static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, b * MII monitoring. Second, if the ARP timer isn't running, we must * start it. */ -static ssize_t bonding_show_arp_interval(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_arp_interval(struct class_device *cd, char *buf) { - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); return sprintf(buf, "%d\n", bond->params.arp_interval) + 1; } -static ssize_t bonding_store_arp_interval(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_arp_interval(struct class_device *cd, const char *buf, size_t count) { int new_value, ret = count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (sscanf(buf, "%d", &new_value) != 1) { printk(KERN_ERR DRV_NAME @@ -655,17 +638,15 @@ static ssize_t bonding_store_arp_interval(struct device *d, out: return ret; } -static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval); +static CLASS_DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval); /* * Show and set the arp targets. */ -static ssize_t bonding_show_arp_targets(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_arp_targets(struct class_device *cd, char *buf) { int i, res = 0; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { if (bond->params.arp_targets[i]) @@ -679,13 +660,11 @@ static ssize_t bonding_show_arp_targets(struct device *d, return res; } -static ssize_t bonding_store_arp_targets(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_arp_targets(struct class_device *cd, const char *buf, size_t count) { u32 newtarget; int i = 0, done = 0, ret = count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); u32 *targets; targets = bond->params.arp_targets; @@ -763,28 +742,24 @@ static ssize_t bonding_store_arp_targets(struct device *d, out: return ret; } -static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets); +static CLASS_DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets); /* * Show and set the up and down delays. These must be multiples of the * MII monitoring value, and are stored internally as the multiplier. * Thus, we must translate to MS for the real world. */ -static ssize_t bonding_show_downdelay(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_downdelay(struct class_device *cd, char *buf) { - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon) + 1; } -static ssize_t bonding_store_downdelay(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_downdelay(struct class_device *cd, const char *buf, size_t count) { int new_value, ret = count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (!(bond->params.miimon)) { printk(KERN_ERR DRV_NAME @@ -825,24 +800,20 @@ static ssize_t bonding_store_downdelay(struct device *d, out: return ret; } -static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay); +static CLASS_DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay); -static ssize_t bonding_show_updelay(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_updelay(struct class_device *cd, char *buf) { - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon) + 1; } -static ssize_t bonding_store_updelay(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_updelay(struct class_device *cd, const char *buf, size_t count) { int new_value, ret = count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (!(bond->params.miimon)) { printk(KERN_ERR DRV_NAME @@ -883,29 +854,25 @@ static ssize_t bonding_store_updelay(struct device *d, out: return ret; } -static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay); +static CLASS_DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay); /* * Show and set the LACP interval. Interface must be down, and the mode * must be set to 802.3ad mode. */ -static ssize_t bonding_show_lacp(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_lacp(struct class_device *cd, char *buf) { - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); return sprintf(buf, "%s %d\n", bond_lacp_tbl[bond->params.lacp_fast].modename, bond->params.lacp_fast) + 1; } -static ssize_t bonding_store_lacp(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_lacp(struct class_device *cd, const char *buf, size_t count) { int new_value, ret = count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (bond->dev->flags & IFF_UP) { printk(KERN_ERR DRV_NAME @@ -939,7 +906,7 @@ static ssize_t bonding_store_lacp(struct device *d, out: return ret; } -static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp); +static CLASS_DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp); /* * Show and set the MII monitor interval. There are two tricky bits @@ -947,21 +914,17 @@ static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_stor * ARP monitoring. Second, if the timer isn't running, we must * start it. */ -static ssize_t bonding_show_miimon(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_miimon(struct class_device *cd, char *buf) { - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); return sprintf(buf, "%d\n", bond->params.miimon) + 1; } -static ssize_t bonding_store_miimon(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, size_t count) { int new_value, ret = count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (sscanf(buf, "%d", &new_value) != 1) { printk(KERN_ERR DRV_NAME @@ -1037,7 +1000,7 @@ static ssize_t bonding_store_miimon(struct device *d, out: return ret; } -static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon); +static CLASS_DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon); /* * Show and set the primary slave. The store function is much @@ -1046,12 +1009,10 @@ static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store * The bond must be a mode that supports a primary for this be * set. */ -static ssize_t bonding_show_primary(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_primary(struct class_device *cd, char *buf) { int count = 0; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (bond->primary_slave) count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1; @@ -1061,13 +1022,11 @@ static ssize_t bonding_show_primary(struct device *d, return count; } -static ssize_t bonding_store_primary(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, size_t count) { int i; struct slave *slave; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); write_lock_bh(&bond->lock); if (!USES_PRIMARY(bond->params.mode)) { @@ -1106,26 +1065,22 @@ static ssize_t bonding_store_primary(struct device *d, write_unlock_bh(&bond->lock); return count; } -static DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary); +static CLASS_DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary); /* * Show and set the use_carrier flag. */ -static ssize_t bonding_show_carrier(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_carrier(struct class_device *cd, char *buf) { - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); return sprintf(buf, "%d\n", bond->params.use_carrier) + 1; } -static ssize_t bonding_store_carrier(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, size_t count) { int new_value, ret = count; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (sscanf(buf, "%d", &new_value) != 1) { @@ -1147,18 +1102,16 @@ static ssize_t bonding_store_carrier(struct device *d, out: return count; } -static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier); +static CLASS_DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier); /* * Show and set currently active_slave. */ -static ssize_t bonding_show_active_slave(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_active_slave(struct class_device *cd, char *buf) { struct slave *curr; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); int count; @@ -1173,15 +1126,13 @@ static ssize_t bonding_show_active_slave(struct device *d, return count; } -static ssize_t bonding_store_active_slave(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t bonding_store_active_slave(struct class_device *cd, const char *buf, size_t count) { int i; struct slave *slave; struct slave *old_active = NULL; struct slave *new_active = NULL; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); write_lock_bh(&bond->lock); if (!USES_PRIMARY(bond->params.mode)) { @@ -1243,18 +1194,16 @@ static ssize_t bonding_store_active_slave(struct device *d, return count; } -static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave); +static CLASS_DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave); /* * Show link status of the bond interface. */ -static ssize_t bonding_show_mii_status(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_mii_status(struct class_device *cd, char *buf) { struct slave *curr; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); read_lock(&bond->curr_slave_lock); curr = bond->curr_active_slave; @@ -1262,18 +1211,16 @@ static ssize_t bonding_show_mii_status(struct device *d, return sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1; } -static DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL); +static CLASS_DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL); /* * Show current 802.3ad aggregator ID. */ -static ssize_t bonding_show_ad_aggregator(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_ad_aggregator(struct class_device *cd, char *buf) { int count = 0; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; @@ -1284,18 +1231,16 @@ static ssize_t bonding_show_ad_aggregator(struct device *d, return count; } -static DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL); +static CLASS_DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL); /* * Show number of active 802.3ad ports. */ -static ssize_t bonding_show_ad_num_ports(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_ad_num_ports(struct class_device *cd, char *buf) { int count = 0; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; @@ -1306,18 +1251,16 @@ static ssize_t bonding_show_ad_num_ports(struct device *d, return count; } -static DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL); +static CLASS_DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL); /* * Show current 802.3ad actor key. */ -static ssize_t bonding_show_ad_actor_key(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_ad_actor_key(struct class_device *cd, char *buf) { int count = 0; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; @@ -1328,18 +1271,16 @@ static ssize_t bonding_show_ad_actor_key(struct device *d, return count; } -static DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL); +static CLASS_DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL); /* * Show current 802.3ad partner key. */ -static ssize_t bonding_show_ad_partner_key(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_ad_partner_key(struct class_device *cd, char *buf) { int count = 0; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; @@ -1350,18 +1291,16 @@ static ssize_t bonding_show_ad_partner_key(struct device *d, return count; } -static DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL); +static CLASS_DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL); /* * Show current 802.3ad partner mac. */ -static ssize_t bonding_show_ad_partner_mac(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t bonding_show_ad_partner_mac(struct class_device *cd, char *buf) { int count = 0; - struct bonding *bond = to_bond(d); + struct bonding *bond = to_bond(cd); if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; @@ -1380,30 +1319,30 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d, return count; } -static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL); +static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL); static struct attribute *per_bond_attrs[] = { - &dev_attr_slaves.attr, - &dev_attr_mode.attr, - &dev_attr_arp_validate.attr, - &dev_attr_arp_interval.attr, - &dev_attr_arp_ip_target.attr, - &dev_attr_downdelay.attr, - &dev_attr_updelay.attr, - &dev_attr_lacp_rate.attr, - &dev_attr_xmit_hash_policy.attr, - &dev_attr_miimon.attr, - &dev_attr_primary.attr, - &dev_attr_use_carrier.attr, - &dev_attr_active_slave.attr, - &dev_attr_mii_status.attr, - &dev_attr_ad_aggregator.attr, - &dev_attr_ad_num_ports.attr, - &dev_attr_ad_actor_key.attr, - &dev_attr_ad_partner_key.attr, - &dev_attr_ad_partner_mac.attr, + &class_device_attr_slaves.attr, + &class_device_attr_mode.attr, + &class_device_attr_arp_validate.attr, + &class_device_attr_arp_interval.attr, + &class_device_attr_arp_ip_target.attr, + &class_device_attr_downdelay.attr, + &class_device_attr_updelay.attr, + &class_device_attr_lacp_rate.attr, + &class_device_attr_xmit_hash_policy.attr, + &class_device_attr_miimon.attr, + &class_device_attr_primary.attr, + &class_device_attr_use_carrier.attr, + &class_device_attr_active_slave.attr, + &class_device_attr_mii_status.attr, + &class_device_attr_ad_aggregator.attr, + &class_device_attr_ad_num_ports.attr, + &class_device_attr_ad_actor_key.attr, + &class_device_attr_ad_partner_key.attr, + &class_device_attr_ad_partner_mac.attr, NULL, }; @@ -1428,26 +1367,11 @@ int bond_create_sysfs(void) if (!firstbond) return -ENODEV; - netdev_class = firstbond->dev->dev.class; + netdev_class = firstbond->dev->class_dev.class; if (!netdev_class) return -ENODEV; ret = class_create_file(netdev_class, &class_attr_bonding_masters); - /* - * Permit multiple loads of the module by ignoring failures to - * create the bonding_masters sysfs file. Bonding devices - * created by second or subsequent loads of the module will - * not be listed in, or controllable by, bonding_masters, but - * will have the usual "bonding" sysfs directory. - * - * This is done to preserve backwards compatibility for - * initscripts/sysconfig, which load bonding multiple times to - * configure multiple bonding devices. - */ - if (ret == -EEXIST) { - netdev_class = NULL; - return 0; - } return ret; @@ -1471,13 +1395,13 @@ int bond_create_sysfs_entry(struct bonding *bond) struct net_device *dev = bond->dev; int err; - err = sysfs_create_group(&(dev->dev.kobj), &bonding_group); + err = sysfs_create_group(&(dev->class_dev.kobj), &bonding_group); if (err) { printk(KERN_EMERG "eek! didn't create group!\n"); } if (expected_refcount < 1) - expected_refcount = atomic_read(&bond->dev->dev.kobj.kref.refcount); + expected_refcount = atomic_read(&bond->dev->class_dev.kobj.kref.refcount); return err; } @@ -1488,6 +1412,6 @@ void bond_destroy_sysfs_entry(struct bonding *bond) { struct net_device *dev = bond->dev; - sysfs_remove_group(&(dev->dev.kobj), &bonding_group); + sysfs_remove_group(&(dev->class_dev.kobj), &bonding_group); } diff --git a/trunk/drivers/net/bonding/bonding.h b/trunk/drivers/net/bonding/bonding.h index 41aa78bf1f78..0978c9ac6d2b 100644 --- a/trunk/drivers/net/bonding/bonding.h +++ b/trunk/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.1.2" -#define DRV_RELDATE "January 20, 2007" +#define DRV_VERSION "3.1.1" +#define DRV_RELDATE "September 26, 2006" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" @@ -237,13 +237,12 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) #define BOND_ARP_VALIDATE_ALL (BOND_ARP_VALIDATE_ACTIVE | \ BOND_ARP_VALIDATE_BACKUP) -static inline int slave_do_arp_validate(struct bonding *bond, - struct slave *slave) +extern inline int slave_do_arp_validate(struct bonding *bond, struct slave *slave) { return bond->params.arp_validate & (1 << slave->state); } -static inline unsigned long slave_last_rx(struct bonding *bond, +extern inline unsigned long slave_last_rx(struct bonding *bond, struct slave *slave) { if (slave_do_arp_validate(bond, slave)) diff --git a/trunk/drivers/net/chelsio/common.h b/trunk/drivers/net/chelsio/common.h index 787f2f2820fe..74758d2c7af8 100644 --- a/trunk/drivers/net/chelsio/common.h +++ b/trunk/drivers/net/chelsio/common.h @@ -324,7 +324,7 @@ struct board_info { unsigned char mdio_phybaseaddr; struct gmac *gmac; struct gphy *gphy; - struct mdio_ops *mdio_ops; + struct mdio_ops *mdio_ops; const char *desc; }; diff --git a/trunk/drivers/net/chelsio/cpl5_cmd.h b/trunk/drivers/net/chelsio/cpl5_cmd.h index e36d45b78cc7..35f565be4fd3 100644 --- a/trunk/drivers/net/chelsio/cpl5_cmd.h +++ b/trunk/drivers/net/chelsio/cpl5_cmd.h @@ -103,7 +103,7 @@ enum CPL_opcode { CPL_MIGRATE_C2T_RPL = 0xDD, CPL_ERROR = 0xD7, - /* internal: driver -> TOM */ + /* internal: driver -> TOM */ CPL_MSS_CHANGE = 0xE1 }; @@ -159,8 +159,8 @@ enum { // TX_PKT_LSO ethernet types }; union opcode_tid { - u32 opcode_tid; - u8 opcode; + u32 opcode_tid; + u8 opcode; }; #define S_OPCODE 24 @@ -234,7 +234,7 @@ struct cpl_pass_accept_req { u32 local_ip; u32 peer_ip; u32 tos_tid; - struct tcp_options tcp_options; + struct tcp_options tcp_options; u8 dst_mac[6]; u16 vlan_tag; u8 src_mac[6]; @@ -250,12 +250,12 @@ struct cpl_pass_accept_rpl { u32 peer_ip; u32 opt0h; union { - u32 opt0l; - struct { - u8 rsvd[3]; - u8 status; - }; + u32 opt0l; + struct { + u8 rsvd[3]; + u8 status; }; + }; }; struct cpl_act_open_req { diff --git a/trunk/drivers/net/chelsio/cxgb2.c b/trunk/drivers/net/chelsio/cxgb2.c index 7d0f24f69777..fd5d821f3f2a 100644 --- a/trunk/drivers/net/chelsio/cxgb2.c +++ b/trunk/drivers/net/chelsio/cxgb2.c @@ -69,14 +69,14 @@ static inline void cancel_mac_stats_update(struct adapter *ap) cancel_delayed_work(&ap->stats_update_task); } -#define MAX_CMDQ_ENTRIES 16384 -#define MAX_CMDQ1_ENTRIES 1024 -#define MAX_RX_BUFFERS 16384 -#define MAX_RX_JUMBO_BUFFERS 16384 +#define MAX_CMDQ_ENTRIES 16384 +#define MAX_CMDQ1_ENTRIES 1024 +#define MAX_RX_BUFFERS 16384 +#define MAX_RX_JUMBO_BUFFERS 16384 #define MAX_TX_BUFFERS_HIGH 16384U #define MAX_TX_BUFFERS_LOW 1536U #define MAX_TX_BUFFERS 1460U -#define MIN_FL_ENTRIES 32 +#define MIN_FL_ENTRIES 32 #define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \ NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ @@ -143,7 +143,7 @@ static void link_report(struct port_info *p) case SPEED_100: s = "100Mbps"; break; } - printk(KERN_INFO "%s: link up, %s, %s-duplex\n", + printk(KERN_INFO "%s: link up, %s, %s-duplex\n", p->dev->name, s, p->link_config.duplex == DUPLEX_FULL ? "full" : "half"); } @@ -233,7 +233,7 @@ static int cxgb_up(struct adapter *adapter) t1_sge_start(adapter->sge); t1_interrupts_enable(adapter); -out_err: + out_err: return err; } @@ -454,21 +454,51 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, const struct cmac_statistics *s; const struct sge_intr_counts *t; struct sge_port_stats ss; - unsigned int len; s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL); - len = sizeof(u64)*(&s->TxFCSErrors + 1 - &s->TxOctetsOK); - memcpy(data, &s->TxOctetsOK, len); - data += len; - - len = sizeof(u64)*(&s->RxFrameTooLongErrors + 1 - &s->RxOctetsOK); - memcpy(data, &s->RxOctetsOK, len); - data += len; + *data++ = s->TxOctetsOK; + *data++ = s->TxOctetsBad; + *data++ = s->TxUnicastFramesOK; + *data++ = s->TxMulticastFramesOK; + *data++ = s->TxBroadcastFramesOK; + *data++ = s->TxPauseFrames; + *data++ = s->TxFramesWithDeferredXmissions; + *data++ = s->TxLateCollisions; + *data++ = s->TxTotalCollisions; + *data++ = s->TxFramesAbortedDueToXSCollisions; + *data++ = s->TxUnderrun; + *data++ = s->TxLengthErrors; + *data++ = s->TxInternalMACXmitError; + *data++ = s->TxFramesWithExcessiveDeferral; + *data++ = s->TxFCSErrors; + + *data++ = s->RxOctetsOK; + *data++ = s->RxOctetsBad; + *data++ = s->RxUnicastFramesOK; + *data++ = s->RxMulticastFramesOK; + *data++ = s->RxBroadcastFramesOK; + *data++ = s->RxPauseFrames; + *data++ = s->RxFCSErrors; + *data++ = s->RxAlignErrors; + *data++ = s->RxSymbolErrors; + *data++ = s->RxDataErrors; + *data++ = s->RxSequenceErrors; + *data++ = s->RxRuntErrors; + *data++ = s->RxJabberErrors; + *data++ = s->RxInternalMACRcvError; + *data++ = s->RxInRangeLengthErrors; + *data++ = s->RxOutOfRangeLengthField; + *data++ = s->RxFrameTooLongErrors; t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss); - memcpy(data, &ss, sizeof(ss)); - data += sizeof(ss); + *data++ = ss.rx_packets; + *data++ = ss.rx_cso_good; + *data++ = ss.tx_packets; + *data++ = ss.tx_cso; + *data++ = ss.tx_tso; + *data++ = ss.vlan_xtract; + *data++ = ss.vlan_insert; t = t1_sge_get_intr_counts(adapter->sge); *data++ = t->rx_drops; @@ -719,7 +749,7 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) return -EINVAL; if (adapter->flags & FULL_INIT_DONE) - return -EBUSY; + return -EBUSY; adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending; adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending; @@ -734,7 +764,7 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) struct adapter *adapter = dev->priv; adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs; - adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce; + adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce; adapter->params.sge.sample_interval_usecs = c->rate_sample_interval; t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge); return 0; @@ -752,9 +782,9 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) static int get_eeprom_len(struct net_device *dev) { - struct adapter *adapter = dev->priv; + struct adapter *adapter = dev->priv; - return t1_is_asic(adapter) ? EEPROM_SIZE : 0; + return t1_is_asic(adapter) ? EEPROM_SIZE : 0; } #define EEPROM_MAGIC(ap) \ @@ -818,7 +848,7 @@ static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd) u32 val; if (!phy->mdio_read) - return -EOPNOTSUPP; + return -EOPNOTSUPP; phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f, &val); data->val_out = val; @@ -830,7 +860,7 @@ static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd) if (!capable(CAP_NET_ADMIN)) return -EPERM; if (!phy->mdio_write) - return -EOPNOTSUPP; + return -EOPNOTSUPP; phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f, data->val_in); break; @@ -849,9 +879,9 @@ static int t1_change_mtu(struct net_device *dev, int new_mtu) struct cmac *mac = adapter->port[dev->if_port].mac; if (!mac->ops->set_mtu) - return -EOPNOTSUPP; + return -EOPNOTSUPP; if (new_mtu < 68) - return -EINVAL; + return -EINVAL; if ((ret = mac->ops->set_mtu(mac, new_mtu))) return ret; dev->mtu = new_mtu; @@ -1181,9 +1211,9 @@ static int __devinit init_one(struct pci_dev *pdev, return 0; -out_release_adapter_res: + out_release_adapter_res: t1_free_sw_modules(adapter); -out_free_dev: + out_free_dev: if (adapter) { if (adapter->regs) iounmap(adapter->regs); @@ -1192,7 +1222,7 @@ static int __devinit init_one(struct pci_dev *pdev, free_netdev(adapter->port[i].dev); } pci_release_regions(pdev); -out_disable_pdev: + out_disable_pdev: pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); return err; @@ -1243,27 +1273,28 @@ static int t1_clock(struct adapter *adapter, int mode) int M_MEM_VAL; enum { - M_CORE_BITS = 9, - T_CORE_VAL = 0, - T_CORE_BITS = 2, - N_CORE_VAL = 0, - N_CORE_BITS = 2, - M_MEM_BITS = 9, - T_MEM_VAL = 0, - T_MEM_BITS = 2, - N_MEM_VAL = 0, - N_MEM_BITS = 2, - NP_LOAD = 1 << 17, - S_LOAD_MEM = 1 << 5, - S_LOAD_CORE = 1 << 6, - S_CLOCK = 1 << 3 + M_CORE_BITS = 9, + T_CORE_VAL = 0, + T_CORE_BITS = 2, + N_CORE_VAL = 0, + N_CORE_BITS = 2, + M_MEM_BITS = 9, + T_MEM_VAL = 0, + T_MEM_BITS = 2, + N_MEM_VAL = 0, + N_MEM_BITS = 2, + NP_LOAD = 1 << 17, + S_LOAD_MEM = 1 << 5, + S_LOAD_CORE = 1 << 6, + S_CLOCK = 1 << 3 }; if (!t1_is_T1B(adapter)) return -ENODEV; /* Can't re-clock this chip. */ - if (mode & 2) + if (mode & 2) { return 0; /* show current mode. */ + } if ((adapter->t1powersave & 1) == (mode & 1)) return -EALREADY; /* ASIC already running in mode. */ @@ -1355,26 +1386,26 @@ static inline void t1_sw_reset(struct pci_dev *pdev) static void __devexit remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct adapter *adapter = dev->priv; - int i; - for_each_port(adapter, i) { - if (test_bit(i, &adapter->registered_device_map)) - unregister_netdev(adapter->port[i].dev); - } + if (dev) { + int i; + struct adapter *adapter = dev->priv; - t1_free_sw_modules(adapter); - iounmap(adapter->regs); + for_each_port(adapter, i) + if (test_bit(i, &adapter->registered_device_map)) + unregister_netdev(adapter->port[i].dev); - while (--i >= 0) { - if (adapter->port[i].dev) - free_netdev(adapter->port[i].dev); - } + t1_free_sw_modules(adapter); + iounmap(adapter->regs); + while (--i >= 0) + if (adapter->port[i].dev) + free_netdev(adapter->port[i].dev); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - t1_sw_reset(pdev); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + t1_sw_reset(pdev); + } } static struct pci_driver driver = { diff --git a/trunk/drivers/net/chelsio/elmer0.h b/trunk/drivers/net/chelsio/elmer0.h index eef655c827d9..9ebecaa97d31 100644 --- a/trunk/drivers/net/chelsio/elmer0.h +++ b/trunk/drivers/net/chelsio/elmer0.h @@ -46,14 +46,14 @@ enum { }; /* ELMER0 registers */ -#define A_ELMER0_VERSION 0x100000 -#define A_ELMER0_PHY_CFG 0x100004 -#define A_ELMER0_INT_ENABLE 0x100008 -#define A_ELMER0_INT_CAUSE 0x10000c -#define A_ELMER0_GPI_CFG 0x100010 -#define A_ELMER0_GPI_STAT 0x100014 -#define A_ELMER0_GPO 0x100018 -#define A_ELMER0_PORT0_MI1_CFG 0x400000 +#define A_ELMER0_VERSION 0x100000 +#define A_ELMER0_PHY_CFG 0x100004 +#define A_ELMER0_INT_ENABLE 0x100008 +#define A_ELMER0_INT_CAUSE 0x10000c +#define A_ELMER0_GPI_CFG 0x100010 +#define A_ELMER0_GPI_STAT 0x100014 +#define A_ELMER0_GPO 0x100018 +#define A_ELMER0_PORT0_MI1_CFG 0x400000 #define S_MI1_MDI_ENABLE 0 #define V_MI1_MDI_ENABLE(x) ((x) << S_MI1_MDI_ENABLE) @@ -111,18 +111,18 @@ enum { #define V_MI1_OP_BUSY(x) ((x) << S_MI1_OP_BUSY) #define F_MI1_OP_BUSY V_MI1_OP_BUSY(1U) -#define A_ELMER0_PORT1_MI1_CFG 0x500000 -#define A_ELMER0_PORT1_MI1_ADDR 0x500004 -#define A_ELMER0_PORT1_MI1_DATA 0x500008 -#define A_ELMER0_PORT1_MI1_OP 0x50000c -#define A_ELMER0_PORT2_MI1_CFG 0x600000 -#define A_ELMER0_PORT2_MI1_ADDR 0x600004 -#define A_ELMER0_PORT2_MI1_DATA 0x600008 -#define A_ELMER0_PORT2_MI1_OP 0x60000c -#define A_ELMER0_PORT3_MI1_CFG 0x700000 -#define A_ELMER0_PORT3_MI1_ADDR 0x700004 -#define A_ELMER0_PORT3_MI1_DATA 0x700008 -#define A_ELMER0_PORT3_MI1_OP 0x70000c +#define A_ELMER0_PORT1_MI1_CFG 0x500000 +#define A_ELMER0_PORT1_MI1_ADDR 0x500004 +#define A_ELMER0_PORT1_MI1_DATA 0x500008 +#define A_ELMER0_PORT1_MI1_OP 0x50000c +#define A_ELMER0_PORT2_MI1_CFG 0x600000 +#define A_ELMER0_PORT2_MI1_ADDR 0x600004 +#define A_ELMER0_PORT2_MI1_DATA 0x600008 +#define A_ELMER0_PORT2_MI1_OP 0x60000c +#define A_ELMER0_PORT3_MI1_CFG 0x700000 +#define A_ELMER0_PORT3_MI1_ADDR 0x700004 +#define A_ELMER0_PORT3_MI1_DATA 0x700008 +#define A_ELMER0_PORT3_MI1_OP 0x70000c /* Simple bit definition for GPI and GP0 registers. */ #define ELMER0_GP_BIT0 0x0001 diff --git a/trunk/drivers/net/chelsio/espi.c b/trunk/drivers/net/chelsio/espi.c index d7c5406a6c3f..4192f0f5b3ee 100644 --- a/trunk/drivers/net/chelsio/espi.c +++ b/trunk/drivers/net/chelsio/espi.c @@ -202,9 +202,9 @@ static void espi_setup_for_pm3393(adapter_t *adapter) static void espi_setup_for_vsc7321(adapter_t *adapter) { - writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0); - writel(0x1f401f4, adapter->regs + A_ESPI_SCH_TOKEN1); - writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2); + writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0); + writel(0x1f401f4, adapter->regs + A_ESPI_SCH_TOKEN1); + writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2); writel(0xa00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK); writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK); writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH); @@ -247,10 +247,10 @@ int t1_espi_init(struct peespi *espi, int mac_type, int nports) writel(V_OUT_OF_SYNC_COUNT(4) | V_DIP2_PARITY_ERR_THRES(3) | V_DIP4_THRES(1), adapter->regs + A_ESPI_MISC_CONTROL); - writel(nports == 4 ? 0x200040 : 0x1000080, + writel(nports == 4 ? 0x200040 : 0x1000080, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2); } else - writel(0x800100, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2); + writel(0x800100, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2); if (mac_type == CHBT_MAC_PM3393) espi_setup_for_pm3393(adapter); @@ -301,8 +301,7 @@ void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val) { struct peespi *espi = adapter->espi; - if (!is_T2(adapter)) - return; + if (!is_T2(adapter)) return; spin_lock(&espi->lock); espi->misc_ctrl = (val & ~MON_MASK) | (espi->misc_ctrl & MON_MASK); @@ -341,31 +340,32 @@ u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait) * compare with t1_espi_get_mon(), it reads espiInTxSop[0 ~ 3] in * one shot, since there is no per port counter on the out side. */ -int t1_espi_get_mon_t204(adapter_t *adapter, u32 *valp, u8 wait) +int +t1_espi_get_mon_t204(adapter_t *adapter, u32 *valp, u8 wait) { - struct peespi *espi = adapter->espi; + struct peespi *espi = adapter->espi; u8 i, nport = (u8)adapter->params.nports; - if (!wait) { - if (!spin_trylock(&espi->lock)) - return -1; - } else - spin_lock(&espi->lock); + if (!wait) { + if (!spin_trylock(&espi->lock)) + return -1; + } else + spin_lock(&espi->lock); - if ((espi->misc_ctrl & MON_MASK) != F_MONITORED_DIRECTION) { + if ( (espi->misc_ctrl & MON_MASK) != F_MONITORED_DIRECTION ) { espi->misc_ctrl = (espi->misc_ctrl & ~MON_MASK) | F_MONITORED_DIRECTION; - writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL); - } + writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL); + } for (i = 0 ; i < nport; i++, valp++) { if (i) { writel(espi->misc_ctrl | V_MONITORED_PORT_NUM(i), adapter->regs + A_ESPI_MISC_CONTROL); } - *valp = readl(adapter->regs + A_ESPI_SCH_TOKEN3); - } + *valp = readl(adapter->regs + A_ESPI_SCH_TOKEN3); + } - writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL); - spin_unlock(&espi->lock); - return 0; + writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL); + spin_unlock(&espi->lock); + return 0; } diff --git a/trunk/drivers/net/chelsio/fpga_defs.h b/trunk/drivers/net/chelsio/fpga_defs.h index ccdb2bc9ae98..17a3c2ba36a3 100644 --- a/trunk/drivers/net/chelsio/fpga_defs.h +++ b/trunk/drivers/net/chelsio/fpga_defs.h @@ -98,9 +98,9 @@ #define A_MI0_DATA_INT 0xb10 /* GMAC registers */ -#define A_GMAC_MACID_LO 0x28 -#define A_GMAC_MACID_HI 0x2c -#define A_GMAC_CSR 0x30 +#define A_GMAC_MACID_LO 0x28 +#define A_GMAC_MACID_HI 0x2c +#define A_GMAC_CSR 0x30 #define S_INTERFACE 0 #define M_INTERFACE 0x3 diff --git a/trunk/drivers/net/chelsio/gmac.h b/trunk/drivers/net/chelsio/gmac.h index 006a2eb2d362..a2b8ad9b5535 100644 --- a/trunk/drivers/net/chelsio/gmac.h +++ b/trunk/drivers/net/chelsio/gmac.h @@ -42,15 +42,8 @@ #include "common.h" -enum { - MAC_STATS_UPDATE_FAST, - MAC_STATS_UPDATE_FULL -}; - -enum { - MAC_DIRECTION_RX = 1, - MAC_DIRECTION_TX = 2 -}; +enum { MAC_STATS_UPDATE_FAST, MAC_STATS_UPDATE_FULL }; +enum { MAC_DIRECTION_RX = 1, MAC_DIRECTION_TX = 2 }; struct cmac_statistics { /* Transmit */ diff --git a/trunk/drivers/net/chelsio/ixf1010.c b/trunk/drivers/net/chelsio/ixf1010.c index 10b2a9a19006..5b8f144e83d4 100644 --- a/trunk/drivers/net/chelsio/ixf1010.c +++ b/trunk/drivers/net/chelsio/ixf1010.c @@ -145,61 +145,48 @@ static void disable_port(struct cmac *mac) t1_tpi_write(mac->adapter, REG_PORT_ENABLE, val); } +#define RMON_UPDATE(mac, name, stat_name) \ + t1_tpi_read((mac)->adapter, MACREG(mac, REG_##name), &val); \ + (mac)->stats.stat_name += val; + /* * Read the current values of the RMON counters and add them to the cumulative * port statistics. The HW RMON counters are cleared by this operation. */ static void port_stats_update(struct cmac *mac) { - static struct { - unsigned int reg; - unsigned int offset; - } hw_stats[] = { - -#define HW_STAT(name, stat_name) \ - { REG_##name, \ - (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL } - - /* Rx stats */ - HW_STAT(RxOctetsTotalOK, RxOctetsOK), - HW_STAT(RxOctetsBad, RxOctetsBad), - HW_STAT(RxUCPkts, RxUnicastFramesOK), - HW_STAT(RxMCPkts, RxMulticastFramesOK), - HW_STAT(RxBCPkts, RxBroadcastFramesOK), - HW_STAT(RxJumboPkts, RxJumboFramesOK), - HW_STAT(RxFCSErrors, RxFCSErrors), - HW_STAT(RxAlignErrors, RxAlignErrors), - HW_STAT(RxLongErrors, RxFrameTooLongErrors), - HW_STAT(RxVeryLongErrors, RxFrameTooLongErrors), - HW_STAT(RxPauseMacControlCounter, RxPauseFrames), - HW_STAT(RxDataErrors, RxDataErrors), - HW_STAT(RxJabberErrors, RxJabberErrors), - HW_STAT(RxRuntErrors, RxRuntErrors), - HW_STAT(RxShortErrors, RxRuntErrors), - HW_STAT(RxSequenceErrors, RxSequenceErrors), - HW_STAT(RxSymbolErrors, RxSymbolErrors), - - /* Tx stats (skip collision stats as we are full-duplex only) */ - HW_STAT(TxOctetsTotalOK, TxOctetsOK), - HW_STAT(TxOctetsBad, TxOctetsBad), - HW_STAT(TxUCPkts, TxUnicastFramesOK), - HW_STAT(TxMCPkts, TxMulticastFramesOK), - HW_STAT(TxBCPkts, TxBroadcastFramesOK), - HW_STAT(TxJumboPkts, TxJumboFramesOK), - HW_STAT(TxPauseFrames, TxPauseFrames), - HW_STAT(TxExcessiveLengthDrop, TxLengthErrors), - HW_STAT(TxUnderrun, TxUnderrun), - HW_STAT(TxCRCErrors, TxFCSErrors) - }, *p = hw_stats; - u64 *stats = (u64 *) &mac->stats; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(hw_stats); i++) { - u32 val; + u32 val; - t1_tpi_read(mac->adapter, MACREG(mac, p->reg), &val); - stats[p->offset] += val; - } + /* Rx stats */ + RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK); + RMON_UPDATE(mac, RxOctetsBad, RxOctetsBad); + RMON_UPDATE(mac, RxUCPkts, RxUnicastFramesOK); + RMON_UPDATE(mac, RxMCPkts, RxMulticastFramesOK); + RMON_UPDATE(mac, RxBCPkts, RxBroadcastFramesOK); + RMON_UPDATE(mac, RxJumboPkts, RxJumboFramesOK); + RMON_UPDATE(mac, RxFCSErrors, RxFCSErrors); + RMON_UPDATE(mac, RxAlignErrors, RxAlignErrors); + RMON_UPDATE(mac, RxLongErrors, RxFrameTooLongErrors); + RMON_UPDATE(mac, RxVeryLongErrors, RxFrameTooLongErrors); + RMON_UPDATE(mac, RxPauseMacControlCounter, RxPauseFrames); + RMON_UPDATE(mac, RxDataErrors, RxDataErrors); + RMON_UPDATE(mac, RxJabberErrors, RxJabberErrors); + RMON_UPDATE(mac, RxRuntErrors, RxRuntErrors); + RMON_UPDATE(mac, RxShortErrors, RxRuntErrors); + RMON_UPDATE(mac, RxSequenceErrors, RxSequenceErrors); + RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors); + + /* Tx stats (skip collision stats as we are full-duplex only) */ + RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK); + RMON_UPDATE(mac, TxOctetsBad, TxOctetsBad); + RMON_UPDATE(mac, TxUCPkts, TxUnicastFramesOK); + RMON_UPDATE(mac, TxMCPkts, TxMulticastFramesOK); + RMON_UPDATE(mac, TxBCPkts, TxBroadcastFramesOK); + RMON_UPDATE(mac, TxJumboPkts, TxJumboFramesOK); + RMON_UPDATE(mac, TxPauseFrames, TxPauseFrames); + RMON_UPDATE(mac, TxExcessiveLengthDrop, TxLengthErrors); + RMON_UPDATE(mac, TxUnderrun, TxUnderrun); + RMON_UPDATE(mac, TxCRCErrors, TxFCSErrors); } /* No-op interrupt operation as this MAC does not support interrupts */ @@ -286,8 +273,7 @@ static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm) static int mac_set_mtu(struct cmac *mac, int mtu) { /* MAX_FRAME_SIZE inludes header + FCS, mtu doesn't */ - if (mtu > (MAX_FRAME_SIZE - 14 - 4)) - return -EINVAL; + if (mtu > (MAX_FRAME_SIZE - 14 - 4)) return -EINVAL; t1_tpi_write(mac->adapter, MACREG(mac, REG_MAX_FRAME_SIZE), mtu + 14 + 4); return 0; @@ -371,8 +357,8 @@ static void enable_port(struct cmac *mac) val |= (1 << index); t1_tpi_write(adapter, REG_PORT_ENABLE, val); - index <<= 2; - if (is_T2(adapter)) { + index <<= 2; + if (is_T2(adapter)) { /* T204: set the Fifo water level & threshold */ t1_tpi_write(adapter, RX_FIFO_HIGH_WATERMARK_BASE + index, 0x740); t1_tpi_write(adapter, RX_FIFO_LOW_WATERMARK_BASE + index, 0x730); @@ -403,10 +389,6 @@ static int mac_disable(struct cmac *mac, int which) return 0; } -#define RMON_UPDATE(mac, name, stat_name) \ - t1_tpi_read((mac)->adapter, MACREG(mac, REG_##name), &val); \ - (mac)->stats.stat_name += val; - /* * This function is called periodically to accumulate the current values of the * RMON counters into the port statistics. Since the counters are only 32 bits @@ -478,12 +460,10 @@ static struct cmac *ixf1010_mac_create(adapter_t *adapter, int index) struct cmac *mac; u32 val; - if (index > 9) - return NULL; + if (index > 9) return NULL; mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL); - if (!mac) - return NULL; + if (!mac) return NULL; mac->ops = &ixf1010_ops; mac->instance = (cmac_instance *)(mac + 1); diff --git a/trunk/drivers/net/chelsio/mv88e1xxx.c b/trunk/drivers/net/chelsio/mv88e1xxx.c index 5867e3b0a887..28ac93ff7c4f 100644 --- a/trunk/drivers/net/chelsio/mv88e1xxx.c +++ b/trunk/drivers/net/chelsio/mv88e1xxx.c @@ -73,8 +73,9 @@ static int mv88e1xxx_interrupt_enable(struct cphy *cphy) t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); elmer |= ELMER0_GP_BIT1; - if (is_T2(cphy->adapter)) - elmer |= ELMER0_GP_BIT2 | ELMER0_GP_BIT3 | ELMER0_GP_BIT4; + if (is_T2(cphy->adapter)) { + elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4; + } t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); } return 0; @@ -91,8 +92,9 @@ static int mv88e1xxx_interrupt_disable(struct cphy *cphy) t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); elmer &= ~ELMER0_GP_BIT1; - if (is_T2(cphy->adapter)) + if (is_T2(cphy->adapter)) { elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4); + } t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); } return 0; @@ -110,8 +112,9 @@ static int mv88e1xxx_interrupt_clear(struct cphy *cphy) if (t1_is_asic(cphy->adapter)) { t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer); elmer |= ELMER0_GP_BIT1; - if (is_T2(cphy->adapter)) + if (is_T2(cphy->adapter)) { elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4; + } t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer); } return 0; @@ -297,7 +300,7 @@ static int mv88e1xxx_interrupt_handler(struct cphy *cphy) /* * Loop until cause reads zero. Need to handle bouncing interrupts. - */ + */ while (1) { u32 cause; @@ -305,16 +308,15 @@ static int mv88e1xxx_interrupt_handler(struct cphy *cphy) MV88E1XXX_INTERRUPT_STATUS_REGISTER, &cause); cause &= INTR_ENABLE_MASK; - if (!cause) - break; + if (!cause) break; if (cause & MV88E1XXX_INTR_LINK_CHNG) { (void) simple_mdio_read(cphy, MV88E1XXX_SPECIFIC_STATUS_REGISTER, &status); - if (status & MV88E1XXX_INTR_LINK_CHNG) + if (status & MV88E1XXX_INTR_LINK_CHNG) { cphy->state |= PHY_LINK_UP; - else { + } else { cphy->state &= ~PHY_LINK_UP; if (cphy->state & PHY_AUTONEG_EN) cphy->state &= ~PHY_AUTONEG_RDY; @@ -358,8 +360,7 @@ static struct cphy *mv88e1xxx_phy_create(adapter_t *adapter, int phy_addr, { struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL); - if (!cphy) - return NULL; + if (!cphy) return NULL; cphy_init(cphy, adapter, phy_addr, &mv88e1xxx_ops, mdio_ops); @@ -376,11 +377,11 @@ static struct cphy *mv88e1xxx_phy_create(adapter_t *adapter, int phy_addr, } (void) mv88e1xxx_downshift_set(cphy, 1); /* Enable downshift */ - /* LED */ + /* LED */ if (is_T2(adapter)) { (void) simple_mdio_write(cphy, MV88E1XXX_LED_CONTROL_REGISTER, 0x1); - } + } return cphy; } diff --git a/trunk/drivers/net/chelsio/my3126.c b/trunk/drivers/net/chelsio/my3126.c index 87dde3e60046..82fed1dd5005 100644 --- a/trunk/drivers/net/chelsio/my3126.c +++ b/trunk/drivers/net/chelsio/my3126.c @@ -10,25 +10,25 @@ static int my3126_reset(struct cphy *cphy, int wait) * This can be done through registers. It is not required since * a full chip reset is used. */ - return 0; + return (0); } static int my3126_interrupt_enable(struct cphy *cphy) { schedule_delayed_work(&cphy->phy_update, HZ/30); t1_tpi_read(cphy->adapter, A_ELMER0_GPO, &cphy->elmer_gpo); - return 0; + return (0); } static int my3126_interrupt_disable(struct cphy *cphy) { cancel_rearming_delayed_work(&cphy->phy_update); - return 0; + return (0); } static int my3126_interrupt_clear(struct cphy *cphy) { - return 0; + return (0); } #define OFFSET(REG_ADDR) (REG_ADDR << 2) @@ -102,7 +102,7 @@ static void my3216_poll(struct work_struct *work) static int my3126_set_loopback(struct cphy *cphy, int on) { - return 0; + return (0); } /* To check the activity LED */ @@ -146,7 +146,7 @@ static int my3126_get_link_status(struct cphy *cphy, if (fc) *fc = PAUSE_RX | PAUSE_TX; - return 0; + return (0); } static void my3126_destroy(struct cphy *cphy) @@ -177,7 +177,7 @@ static struct cphy *my3126_phy_create(adapter_t *adapter, INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll); cphy->bmsr = 0; - return cphy; + return (cphy); } /* Chip Reset */ @@ -198,7 +198,7 @@ static int my3126_phy_reset(adapter_t * adapter) val |= 0x8000; t1_tpi_write(adapter, A_ELMER0_GPO, val); udelay(100); - return 0; + return (0); } struct gphy t1_my3126_ops = { diff --git a/trunk/drivers/net/chelsio/pm3393.c b/trunk/drivers/net/chelsio/pm3393.c index 69129edeefd6..63cabeb98afe 100644 --- a/trunk/drivers/net/chelsio/pm3393.c +++ b/trunk/drivers/net/chelsio/pm3393.c @@ -446,51 +446,17 @@ static void pm3393_rmon_update(struct adapter *adapter, u32 offs, u64 *val, *val += 1ull << 40; } +#define RMON_UPDATE(mac, name, stat_name) \ + pm3393_rmon_update((mac)->adapter, OFFSET(name), \ + &(mac)->stats.stat_name, \ + (ro &((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) + + static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, int flag) { - static struct { - unsigned int reg; - unsigned int offset; - } hw_stats [] = { - -#define HW_STAT(name, stat_name) \ - { name, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL } - - /* Rx stats */ - HW_STAT(RxOctetsReceivedOK, RxOctetsOK), - HW_STAT(RxUnicastFramesReceivedOK, RxUnicastFramesOK), - HW_STAT(RxMulticastFramesReceivedOK, RxMulticastFramesOK), - HW_STAT(RxBroadcastFramesReceivedOK, RxBroadcastFramesOK), - HW_STAT(RxPAUSEMACCtrlFramesReceived, RxPauseFrames), - HW_STAT(RxFrameCheckSequenceErrors, RxFCSErrors), - HW_STAT(RxFramesLostDueToInternalMACErrors, - RxInternalMACRcvError), - HW_STAT(RxSymbolErrors, RxSymbolErrors), - HW_STAT(RxInRangeLengthErrors, RxInRangeLengthErrors), - HW_STAT(RxFramesTooLongErrors , RxFrameTooLongErrors), - HW_STAT(RxJabbers, RxJabberErrors), - HW_STAT(RxFragments, RxRuntErrors), - HW_STAT(RxUndersizedFrames, RxRuntErrors), - HW_STAT(RxJumboFramesReceivedOK, RxJumboFramesOK), - HW_STAT(RxJumboOctetsReceivedOK, RxJumboOctetsOK), - - /* Tx stats */ - HW_STAT(TxOctetsTransmittedOK, TxOctetsOK), - HW_STAT(TxFramesLostDueToInternalMACTransmissionError, - TxInternalMACXmitError), - HW_STAT(TxTransmitSystemError, TxFCSErrors), - HW_STAT(TxUnicastFramesTransmittedOK, TxUnicastFramesOK), - HW_STAT(TxMulticastFramesTransmittedOK, TxMulticastFramesOK), - HW_STAT(TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK), - HW_STAT(TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames), - HW_STAT(TxJumboFramesReceivedOK, TxJumboFramesOK), - HW_STAT(TxJumboOctetsReceivedOK, TxJumboOctetsOK) - }, *p = hw_stats; - u64 ro; - u32 val0, val1, val2, val3; - u64 *stats = (u64 *) &mac->stats; - unsigned int i; + u64 ro; + u32 val0, val1, val2, val3; /* Snap the counters */ pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL, @@ -504,14 +470,35 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) | (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48); - for (i = 0; i < ARRAY_SIZE(hw_stats); i++) { - unsigned reg = p->reg - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW; - - pm3393_rmon_update((mac)->adapter, OFFSET(p->reg), - stats + p->offset, ro & (reg >> 2)); - } - - + /* Rx stats */ + RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK); + RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK); + RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK); + RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK); + RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames); + RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors); + RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors, + RxInternalMACRcvError); + RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors); + RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors); + RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors); + RMON_UPDATE(mac, RxJabbers, RxJabberErrors); + RMON_UPDATE(mac, RxFragments, RxRuntErrors); + RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors); + RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK); + RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK); + + /* Tx stats */ + RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK); + RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError, + TxInternalMACXmitError); + RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors); + RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK); + RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK); + RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK); + RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames); + RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK); + RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK); return &mac->stats; } @@ -547,9 +534,9 @@ static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6]) /* Store local copy */ memcpy(cmac->instance->mac_addr, ma, 6); - lo = ((u32) ma[1] << 8) | (u32) ma[0]; + lo = ((u32) ma[1] << 8) | (u32) ma[0]; mid = ((u32) ma[3] << 8) | (u32) ma[2]; - hi = ((u32) ma[5] << 8) | (u32) ma[4]; + hi = ((u32) ma[5] << 8) | (u32) ma[4]; /* Disable Rx/Tx MAC before configuring it. */ if (enabled) diff --git a/trunk/drivers/net/chelsio/sge.c b/trunk/drivers/net/chelsio/sge.c index 89a682702fa9..659cb2252e44 100644 --- a/trunk/drivers/net/chelsio/sge.c +++ b/trunk/drivers/net/chelsio/sge.c @@ -71,9 +71,12 @@ #define SGE_FREEL_REFILL_THRESH 16 #define SGE_RESPQ_E_N 1024 #define SGE_INTRTIMER_NRES 1000 +#define SGE_RX_COPY_THRES 256 #define SGE_RX_SM_BUF_SIZE 1536 #define SGE_TX_DESC_MAX_PLEN 16384 +# define SGE_RX_DROP_THRES 2 + #define SGE_RESPQ_REPLENISH_THRES (SGE_RESPQ_E_N / 4) /* @@ -82,6 +85,10 @@ */ #define TX_RECLAIM_PERIOD (HZ / 4) +#ifndef NET_IP_ALIGN +# define NET_IP_ALIGN 2 +#endif + #define M_CMD_LEN 0x7fffffff #define V_CMD_LEN(v) (v) #define G_CMD_LEN(v) ((v) & M_CMD_LEN) @@ -188,7 +195,7 @@ struct cmdQ { struct cmdQ_e *entries; /* HW command descriptor Q */ struct cmdQ_ce *centries; /* SW command context descriptor Q */ dma_addr_t dma_addr; /* DMA addr HW command descriptor Q */ - spinlock_t lock; /* Lock to protect cmdQ enqueuing */ + spinlock_t lock; /* Lock to protect cmdQ enqueuing */ }; struct freelQ { @@ -234,9 +241,9 @@ struct sched_port { /* Per T204 device */ struct sched { ktime_t last_updated; /* last time quotas were computed */ - unsigned int max_avail; /* max bits to be sent to any port */ - unsigned int port; /* port index (round robin ports) */ - unsigned int num; /* num skbs in per port queues */ + unsigned int max_avail; /* max bits to be sent to any port */ + unsigned int port; /* port index (round robin ports) */ + unsigned int num; /* num skbs in per port queues */ struct sched_port p[MAX_NPORTS]; struct tasklet_struct sched_tsk;/* tasklet used to run scheduler */ }; @@ -252,10 +259,10 @@ static void restart_sched(unsigned long); * contention. */ struct sge { - struct adapter *adapter; /* adapter backpointer */ + struct adapter *adapter; /* adapter backpointer */ struct net_device *netdev; /* netdevice backpointer */ - struct freelQ freelQ[SGE_FREELQ_N]; /* buffer free lists */ - struct respQ respQ; /* response Q */ + struct freelQ freelQ[SGE_FREELQ_N]; /* buffer free lists */ + struct respQ respQ; /* response Q */ unsigned long stopped_tx_queues; /* bitmap of suspended Tx queues */ unsigned int rx_pkt_pad; /* RX padding for L2 packets */ unsigned int jumbo_fl; /* jumbo freelist Q index */ @@ -453,7 +460,7 @@ static struct sk_buff *sched_skb(struct sge *sge, struct sk_buff *skb, if (credits < MAX_SKB_FRAGS + 1) goto out; -again: + again: for (i = 0; i < MAX_NPORTS; i++) { s->port = ++s->port & (MAX_NPORTS - 1); skbq = &s->p[s->port].skbq; @@ -476,8 +483,8 @@ static struct sk_buff *sched_skb(struct sge *sge, struct sk_buff *skb, if (update-- && sched_update_avail(sge)) goto again; -out: - /* If there are more pending skbs, we use the hardware to schedule us + out: + /* If there are more pending skbs, we use the hardware to schedule us * again. */ if (s->num && !skb) { @@ -568,10 +575,11 @@ static int alloc_rx_resources(struct sge *sge, struct sge_params *p) q->size = p->freelQ_size[i]; q->dma_offset = sge->rx_pkt_pad ? 0 : NET_IP_ALIGN; size = sizeof(struct freelQ_e) * q->size; - q->entries = pci_alloc_consistent(pdev, size, &q->dma_addr); + q->entries = (struct freelQ_e *) + pci_alloc_consistent(pdev, size, &q->dma_addr); if (!q->entries) goto err_no_mem; - + memset(q->entries, 0, size); size = sizeof(struct freelQ_ce) * q->size; q->centries = kzalloc(size, GFP_KERNEL); if (!q->centries) @@ -605,10 +613,11 @@ static int alloc_rx_resources(struct sge *sge, struct sge_params *p) sge->respQ.size = SGE_RESPQ_E_N; sge->respQ.credits = 0; size = sizeof(struct respQ_e) * sge->respQ.size; - sge->respQ.entries = + sge->respQ.entries = (struct respQ_e *) pci_alloc_consistent(pdev, size, &sge->respQ.dma_addr); if (!sge->respQ.entries) goto err_no_mem; + memset(sge->respQ.entries, 0, size); return 0; err_no_mem: @@ -628,12 +637,20 @@ static void free_cmdQ_buffers(struct sge *sge, struct cmdQ *q, unsigned int n) q->in_use -= n; ce = &q->centries[cidx]; while (n--) { - if (likely(pci_unmap_len(ce, dma_len))) { - pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr), - pci_unmap_len(ce, dma_len), - PCI_DMA_TODEVICE); - if (q->sop) + if (q->sop) { + if (likely(pci_unmap_len(ce, dma_len))) { + pci_unmap_single(pdev, + pci_unmap_addr(ce, dma_addr), + pci_unmap_len(ce, dma_len), + PCI_DMA_TODEVICE); q->sop = 0; + } + } else { + if (likely(pci_unmap_len(ce, dma_len))) { + pci_unmap_page(pdev, pci_unmap_addr(ce, dma_addr), + pci_unmap_len(ce, dma_len), + PCI_DMA_TODEVICE); + } } if (ce->skb) { dev_kfree_skb_any(ce->skb); @@ -694,10 +711,11 @@ static int alloc_tx_resources(struct sge *sge, struct sge_params *p) q->stop_thres = 0; spin_lock_init(&q->lock); size = sizeof(struct cmdQ_e) * q->size; - q->entries = pci_alloc_consistent(pdev, size, &q->dma_addr); + q->entries = (struct cmdQ_e *) + pci_alloc_consistent(pdev, size, &q->dma_addr); if (!q->entries) goto err_no_mem; - + memset(q->entries, 0, size); size = sizeof(struct cmdQ_ce) * q->size; q->centries = kzalloc(size, GFP_KERNEL); if (!q->centries) @@ -752,7 +770,7 @@ void t1_set_vlan_accel(struct adapter *adapter, int on_off) static void configure_sge(struct sge *sge, struct sge_params *p) { struct adapter *ap = sge->adapter; - + writel(0, ap->regs + A_SG_CONTROL); setup_ring_params(ap, sge->cmdQ[0].dma_addr, sge->cmdQ[0].size, A_SG_CMD0BASELWR, A_SG_CMD0BASEUPR, A_SG_CMD0SIZE); @@ -832,6 +850,7 @@ static void refill_free_list(struct sge *sge, struct freelQ *q) struct freelQ_e *e = &q->entries[q->pidx]; unsigned int dma_len = q->rx_buffer_size - q->dma_offset; + while (q->credits < q->size) { struct sk_buff *skb; dma_addr_t mapping; @@ -843,8 +862,6 @@ static void refill_free_list(struct sge *sge, struct freelQ *q) skb_reserve(skb, q->dma_offset); mapping = pci_map_single(pdev, skb->data, dma_len, PCI_DMA_FROMDEVICE); - skb_reserve(skb, sge->rx_pkt_pad); - ce->skb = skb; pci_unmap_addr_set(ce, dma_addr, mapping); pci_unmap_len_set(ce, dma_len, dma_len); @@ -864,6 +881,7 @@ static void refill_free_list(struct sge *sge, struct freelQ *q) } q->credits++; } + } /* @@ -1023,10 +1041,6 @@ static void recycle_fl_buf(struct freelQ *fl, int idx) } } -static int copybreak __read_mostly = 256; -module_param(copybreak, int, 0); -MODULE_PARM_DESC(copybreak, "Receive copy threshold"); - /** * get_packet - return the next ingress packet buffer * @pdev: the PCI device that received the packet @@ -1046,42 +1060,45 @@ MODULE_PARM_DESC(copybreak, "Receive copy threshold"); * be copied but there is no memory for the copy. */ static inline struct sk_buff *get_packet(struct pci_dev *pdev, - struct freelQ *fl, unsigned int len) + struct freelQ *fl, unsigned int len, + int dma_pad, int skb_pad, + unsigned int copy_thres, + unsigned int drop_thres) { struct sk_buff *skb; - const struct freelQ_ce *ce = &fl->centries[fl->cidx]; - - if (len < copybreak) { - skb = alloc_skb(len + 2, GFP_ATOMIC); - if (!skb) - goto use_orig_buf; + struct freelQ_ce *ce = &fl->centries[fl->cidx]; - skb_reserve(skb, 2); /* align IP header */ - skb_put(skb, len); - pci_dma_sync_single_for_cpu(pdev, + if (len < copy_thres) { + skb = alloc_skb(len + skb_pad, GFP_ATOMIC); + if (likely(skb != NULL)) { + skb_reserve(skb, skb_pad); + skb_put(skb, len); + pci_dma_sync_single_for_cpu(pdev, pci_unmap_addr(ce, dma_addr), - pci_unmap_len(ce, dma_len), + pci_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE); - memcpy(skb->data, ce->skb->data, len); - pci_dma_sync_single_for_device(pdev, - pci_unmap_addr(ce, dma_addr), - pci_unmap_len(ce, dma_len), - PCI_DMA_FROMDEVICE); + memcpy(skb->data, ce->skb->data + dma_pad, len); + pci_dma_sync_single_for_device(pdev, + pci_unmap_addr(ce, dma_addr), + pci_unmap_len(ce, dma_len), + PCI_DMA_FROMDEVICE); + } else if (!drop_thres) + goto use_orig_buf; + recycle_fl_buf(fl, fl->cidx); return skb; } -use_orig_buf: - if (fl->credits < 2) { + if (fl->credits < drop_thres) { recycle_fl_buf(fl, fl->cidx); return NULL; } +use_orig_buf: pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr), pci_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE); skb = ce->skb; - prefetch(skb->data); - + skb_reserve(skb, dma_pad); skb_put(skb, len); return skb; } @@ -1120,7 +1137,6 @@ static void unexpected_offload(struct adapter *adapter, struct freelQ *fl) static inline unsigned int compute_large_page_tx_descs(struct sk_buff *skb) { unsigned int count = 0; - if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN) { unsigned int nfrags = skb_shinfo(skb)->nr_frags; unsigned int i, len = skb->len - skb->data_len; @@ -1327,7 +1343,7 @@ static void restart_sched(unsigned long arg) while ((skb = sched_skb(sge, NULL, credits)) != NULL) { unsigned int genbit, pidx, count; count = 1 + skb_shinfo(skb)->nr_frags; - count += compute_large_page_tx_descs(skb); + count += compute_large_page_tx_descs(skb); q->in_use += count; genbit = q->genbit; pidx = q->pidx; @@ -1359,25 +1375,27 @@ static void restart_sched(unsigned long arg) * * Process an ingress ethernet pakcet and deliver it to the stack. */ -static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) +static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) { struct sk_buff *skb; - const struct cpl_rx_pkt *p; + struct cpl_rx_pkt *p; struct adapter *adapter = sge->adapter; struct sge_port_stats *st; - skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad); + skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad, + sge->rx_pkt_pad, 2, SGE_RX_COPY_THRES, + SGE_RX_DROP_THRES); if (unlikely(!skb)) { sge->stats.rx_drops++; - return; + return 0; } - p = (const struct cpl_rx_pkt *) skb->data; + p = (struct cpl_rx_pkt *)skb->data; + skb_pull(skb, sizeof(*p)); if (p->iff >= adapter->params.nports) { kfree_skb(skb); - return; + return 0; } - __skb_pull(skb, sizeof(*p)); skb->dev = adapter->port[p->iff].dev; skb->dev->last_rx = jiffies; @@ -1409,6 +1427,7 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) netif_rx(skb); #endif } + return 0; } /* @@ -1429,28 +1448,29 @@ static inline int enough_free_Tx_descs(const struct cmdQ *q) static void restart_tx_queues(struct sge *sge) { struct adapter *adap = sge->adapter; - int i; - if (!enough_free_Tx_descs(&sge->cmdQ[0])) - return; + if (enough_free_Tx_descs(&sge->cmdQ[0])) { + int i; - for_each_port(adap, i) { - struct net_device *nd = adap->port[i].dev; + for_each_port(adap, i) { + struct net_device *nd = adap->port[i].dev; - if (test_and_clear_bit(nd->if_port, &sge->stopped_tx_queues) && - netif_running(nd)) { - sge->stats.cmdQ_restarted[2]++; - netif_wake_queue(nd); + if (test_and_clear_bit(nd->if_port, + &sge->stopped_tx_queues) && + netif_running(nd)) { + sge->stats.cmdQ_restarted[2]++; + netif_wake_queue(nd); + } } } } /* - * update_tx_info is called from the interrupt handler/NAPI to return cmdQ0 + * update_tx_info is called from the interrupt handler/NAPI to return cmdQ0 * information. */ -static unsigned int update_tx_info(struct adapter *adapter, - unsigned int flags, +static unsigned int update_tx_info(struct adapter *adapter, + unsigned int flags, unsigned int pr0) { struct sge *sge = adapter->sge; @@ -1490,30 +1510,29 @@ static int process_responses(struct adapter *adapter, int budget) struct sge *sge = adapter->sge; struct respQ *q = &sge->respQ; struct respQ_e *e = &q->entries[q->cidx]; - int done = 0; + int budget_left = budget; unsigned int flags = 0; unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0}; + - while (done < budget && e->GenerationBit == q->genbit) { + while (likely(budget_left && e->GenerationBit == q->genbit)) { flags |= e->Qsleeping; - + cmdq_processed[0] += e->Cmdq0CreditReturn; cmdq_processed[1] += e->Cmdq1CreditReturn; - + /* We batch updates to the TX side to avoid cacheline * ping-pong of TX state information on MP where the sender * might run on a different CPU than this function... */ - if (unlikely((flags & F_CMDQ0_ENABLE) || cmdq_processed[0] > 64)) { + if (unlikely(flags & F_CMDQ0_ENABLE || cmdq_processed[0] > 64)) { flags = update_tx_info(adapter, flags, cmdq_processed[0]); cmdq_processed[0] = 0; } - if (unlikely(cmdq_processed[1] > 16)) { sge->cmdQ[1].processed += cmdq_processed[1]; cmdq_processed[1] = 0; } - if (likely(e->DataValid)) { struct freelQ *fl = &sge->freelQ[e->FreelistQid]; @@ -1523,16 +1542,12 @@ static int process_responses(struct adapter *adapter, int budget) else sge_rx(sge, fl, e->BufferLength); - ++done; - /* * Note: this depends on each packet consuming a * single free-list buffer; cf. the BUG above. */ if (++fl->cidx == fl->size) fl->cidx = 0; - prefetch(fl->centries[fl->cidx].skb); - if (unlikely(--fl->credits < fl->size - SGE_FREEL_REFILL_THRESH)) refill_free_list(sge, fl); @@ -1551,20 +1566,14 @@ static int process_responses(struct adapter *adapter, int budget) writel(q->credits, adapter->regs + A_SG_RSPQUEUECREDIT); q->credits = 0; } + --budget_left; } - flags = update_tx_info(adapter, flags, cmdq_processed[0]); + flags = update_tx_info(adapter, flags, cmdq_processed[0]); sge->cmdQ[1].processed += cmdq_processed[1]; - return done; -} - -static inline int responses_pending(const struct adapter *adapter) -{ - const struct respQ *Q = &adapter->sge->respQ; - const struct respQ_e *e = &Q->entries[Q->cidx]; - - return (e->GenerationBit == Q->genbit); + budget -= budget_left; + return budget; } #ifdef CONFIG_CHELSIO_T1_NAPI @@ -1576,25 +1585,19 @@ static inline int responses_pending(const struct adapter *adapter) * which the caller must ensure is a valid pure response. Returns 1 if it * encounters a valid data-carrying response, 0 otherwise. */ -static int process_pure_responses(struct adapter *adapter) +static int process_pure_responses(struct adapter *adapter, struct respQ_e *e) { struct sge *sge = adapter->sge; struct respQ *q = &sge->respQ; - struct respQ_e *e = &q->entries[q->cidx]; - const struct freelQ *fl = &sge->freelQ[e->FreelistQid]; unsigned int flags = 0; unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0}; - prefetch(fl->centries[fl->cidx].skb); - if (e->DataValid) - return 1; - do { flags |= e->Qsleeping; cmdq_processed[0] += e->Cmdq0CreditReturn; cmdq_processed[1] += e->Cmdq1CreditReturn; - + e++; if (unlikely(++q->cidx == q->size)) { q->cidx = 0; @@ -1610,7 +1613,7 @@ static int process_pure_responses(struct adapter *adapter) sge->stats.pure_rsps++; } while (e->GenerationBit == q->genbit && !e->DataValid); - flags = update_tx_info(adapter, flags, cmdq_processed[0]); + flags = update_tx_info(adapter, flags, cmdq_processed[0]); sge->cmdQ[1].processed += cmdq_processed[1]; return e->GenerationBit == q->genbit; @@ -1624,20 +1627,23 @@ static int process_pure_responses(struct adapter *adapter) int t1_poll(struct net_device *dev, int *budget) { struct adapter *adapter = dev->priv; - int work_done; + int effective_budget = min(*budget, dev->quota); + int work_done = process_responses(adapter, effective_budget); - work_done = process_responses(adapter, min(*budget, dev->quota)); *budget -= work_done; dev->quota -= work_done; - if (unlikely(responses_pending(adapter))) + if (work_done >= effective_budget) return 1; - netif_rx_complete(dev); + spin_lock_irq(&adapter->async_lock); + __netif_rx_complete(dev); writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); + writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA, + adapter->regs + A_PL_ENABLE); + spin_unlock_irq(&adapter->async_lock); return 0; - } /* @@ -1646,33 +1652,44 @@ int t1_poll(struct net_device *dev, int *budget) irqreturn_t t1_interrupt(int irq, void *data) { struct adapter *adapter = data; + struct net_device *dev = adapter->sge->netdev; struct sge *sge = adapter->sge; - int handled; - - if (likely(responses_pending(adapter))) { - struct net_device *dev = sge->netdev; + u32 cause; + int handled = 0; - writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE); + cause = readl(adapter->regs + A_PL_CAUSE); + if (cause == 0 || cause == ~0) + return IRQ_NONE; - if (__netif_rx_schedule_prep(dev)) { - if (process_pure_responses(adapter)) - __netif_rx_schedule(dev); - else { - /* no data, no NAPI needed */ - writel(sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); - netif_poll_enable(dev); /* undo schedule_prep */ + spin_lock(&adapter->async_lock); + if (cause & F_PL_INTR_SGE_DATA) { + struct respQ *q = &adapter->sge->respQ; + struct respQ_e *e = &q->entries[q->cidx]; + + handled = 1; + writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE); + + if (e->GenerationBit == q->genbit && + __netif_rx_schedule_prep(dev)) { + if (e->DataValid || process_pure_responses(adapter, e)) { + /* mask off data IRQ */ + writel(adapter->slow_intr_mask, + adapter->regs + A_PL_ENABLE); + __netif_rx_schedule(sge->netdev); + goto unlock; } - } - return IRQ_HANDLED; - } + /* no data, no NAPI needed */ + netif_poll_enable(dev); - spin_lock(&adapter->async_lock); - handled = t1_slow_intr_handler(adapter); - spin_unlock(&adapter->async_lock); + } + writel(q->cidx, adapter->regs + A_SG_SLEEPING); + } else + handled = t1_slow_intr_handler(adapter); if (!handled) sge->stats.unhandled_irqs++; - +unlock: + spin_unlock(&adapter->async_lock); return IRQ_RETVAL(handled != 0); } @@ -1695,13 +1712,17 @@ irqreturn_t t1_interrupt(int irq, void *data) irqreturn_t t1_interrupt(int irq, void *cookie) { int work_done; + struct respQ_e *e; struct adapter *adapter = cookie; + struct respQ *Q = &adapter->sge->respQ; spin_lock(&adapter->async_lock); + e = &Q->entries[Q->cidx]; + prefetch(e); writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE); - if (likely(responses_pending(adapter))) + if (likely(e->GenerationBit == Q->genbit)) work_done = process_responses(adapter, -1); else work_done = t1_slow_intr_handler(adapter); @@ -1775,7 +1796,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter, * through the scheduler. */ if (sge->tx_sched && !qid && skb->dev) { -use_sched: + use_sched: use_sched_skb = 1; /* Note that the scheduler might return a different skb than * the one passed in. @@ -1879,7 +1900,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) cpl = (struct cpl_tx_pkt *)hdr; } else { /* - * Packets shorter than ETH_HLEN can break the MAC, drop them + * Packets shorter than ETH_HLEN can break the MAC, drop them * early. Also, we may get oversized packets because some * parts of the kernel don't handle our unusual hard_header_len * right, drop those too. @@ -1963,9 +1984,9 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) * then silently discard to avoid leak. */ if (unlikely(ret != NETDEV_TX_OK && skb != orig_skb)) { - dev_kfree_skb_any(skb); + dev_kfree_skb_any(skb); ret = NETDEV_TX_OK; - } + } return ret; } @@ -2078,35 +2099,31 @@ static void espibug_workaround_t204(unsigned long data) if (adapter->open_device_map & PORT_MASK) { int i; - - if (t1_espi_get_mon_t204(adapter, &(seop[0]), 0) < 0) + if (t1_espi_get_mon_t204(adapter, &(seop[0]), 0) < 0) { return; - + } for (i = 0; i < nports; i++) { - struct sk_buff *skb = sge->espibug_skb[i]; - - if (!netif_running(adapter->port[i].dev) || - netif_queue_stopped(adapter->port[i].dev) || - !seop[i] || ((seop[i] & 0xfff) != 0) || !skb) - continue; - - if (!skb->cb[0]) { - u8 ch_mac_addr[ETH_ALEN] = { - 0x0, 0x7, 0x43, 0x0, 0x0, 0x0 - }; - - memcpy(skb->data + sizeof(struct cpl_tx_pkt), - ch_mac_addr, ETH_ALEN); - memcpy(skb->data + skb->len - 10, - ch_mac_addr, ETH_ALEN); - skb->cb[0] = 0xff; + struct sk_buff *skb = sge->espibug_skb[i]; + if ( (netif_running(adapter->port[i].dev)) && + !(netif_queue_stopped(adapter->port[i].dev)) && + (seop[i] && ((seop[i] & 0xfff) == 0)) && + skb ) { + if (!skb->cb[0]) { + u8 ch_mac_addr[ETH_ALEN] = + {0x0, 0x7, 0x43, 0x0, 0x0, 0x0}; + memcpy(skb->data + sizeof(struct cpl_tx_pkt), + ch_mac_addr, ETH_ALEN); + memcpy(skb->data + skb->len - 10, + ch_mac_addr, ETH_ALEN); + skb->cb[0] = 0xff; + } + + /* bump the reference count to avoid freeing of + * the skb once the DMA has completed. + */ + skb = skb_get(skb); + t1_sge_tx(skb, adapter, 0, adapter->port[i].dev); } - - /* bump the reference count to avoid freeing of - * the skb once the DMA has completed. - */ - skb = skb_get(skb); - t1_sge_tx(skb, adapter, 0, adapter->port[i].dev); } } mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout); @@ -2175,8 +2192,9 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter, if (adapter->params.nports > 1) { tx_sched_init(sge); sge->espibug_timer.function = espibug_workaround_t204; - } else + } else { sge->espibug_timer.function = espibug_workaround; + } sge->espibug_timer.data = (unsigned long)sge->adapter; sge->espibug_timeout = 1; @@ -2184,7 +2202,7 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter, if (adapter->params.nports > 1) sge->espibug_timeout = HZ/100; } - + p->cmdQ_size[0] = SGE_CMDQ0_E_N; p->cmdQ_size[1] = SGE_CMDQ1_E_N; diff --git a/trunk/drivers/net/chelsio/subr.c b/trunk/drivers/net/chelsio/subr.c index c2522cdfab37..22ed9a383c08 100644 --- a/trunk/drivers/net/chelsio/subr.c +++ b/trunk/drivers/net/chelsio/subr.c @@ -223,13 +223,13 @@ static int fpga_slow_intr(adapter_t *adapter) t1_sge_intr_error_handler(adapter->sge); if (cause & FPGA_PCIX_INTERRUPT_GMAC) - fpga_phy_intr_handler(adapter); + fpga_phy_intr_handler(adapter); if (cause & FPGA_PCIX_INTERRUPT_TP) { - /* + /* * FPGA doesn't support MC4 interrupts and it requires * this odd layer of indirection for MC5. - */ + */ u32 tp_cause = readl(adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE); /* Clear TP interrupt */ @@ -262,7 +262,8 @@ static int mi1_wait_until_ready(adapter_t *adapter, int mi1_reg) udelay(10); } while (busy && --attempts); if (busy) - CH_ALERT("%s: MDIO operation timed out\n", adapter->name); + CH_ALERT("%s: MDIO operation timed out\n", + adapter->name); return busy; } @@ -604,23 +605,22 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) switch (board_info(adapter)->board) { #ifdef CONFIG_CHELSIO_T1_1G - case CHBT_BOARD_CHT204: - case CHBT_BOARD_CHT204E: - case CHBT_BOARD_CHN204: - case CHBT_BOARD_CHT204V: { - int i, port_bit; + case CHBT_BOARD_CHT204: + case CHBT_BOARD_CHT204E: + case CHBT_BOARD_CHN204: + case CHBT_BOARD_CHT204V: { + int i, port_bit; for_each_port(adapter, i) { port_bit = i + 1; - if (!(cause & (1 << port_bit))) - continue; + if (!(cause & (1 << port_bit))) continue; - phy = adapter->port[i].phy; + phy = adapter->port[i].phy; phy_cause = phy->ops->interrupt_handler(phy); if (phy_cause & cphy_cause_link_change) t1_link_changed(adapter, i); } - break; - } + break; + } case CHBT_BOARD_CHT101: if (cause & ELMER0_GP_BIT1) { /* Marvell 88E1111 interrupt */ phy = adapter->port[0].phy; @@ -631,13 +631,13 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) break; case CHBT_BOARD_7500: { int p; - /* + /* * Elmer0's interrupt cause isn't useful here because there is * only one bit that can be set for all 4 ports. This means * we are forced to check every PHY's interrupt status * register to see who initiated the interrupt. - */ - for_each_port(adapter, p) { + */ + for_each_port(adapter, p) { phy = adapter->port[p].phy; phy_cause = phy->ops->interrupt_handler(phy); if (phy_cause & cphy_cause_link_change) @@ -658,7 +658,7 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) break; case CHBT_BOARD_8000: case CHBT_BOARD_CHT110: - CH_DBG(adapter, INTR, "External interrupt cause 0x%x\n", + CH_DBG(adapter, INTR, "External interrupt cause 0x%x\n", cause); if (cause & ELMER0_GP_BIT1) { /* PMC3393 INTB */ struct cmac *mac = adapter->port[0].mac; @@ -670,9 +670,9 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect); - CH_MSG(adapter, INFO, LINK, "XPAK %s\n", + CH_MSG(adapter, INFO, LINK, "XPAK %s\n", mod_detect ? "removed" : "inserted"); - } + } break; #ifdef CONFIG_CHELSIO_T1_COUGAR case CHBT_BOARD_COUGAR: @@ -688,8 +688,7 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) for_each_port(adapter, i) { port_bit = i ? i + 1 : 0; - if (!(cause & (1 << port_bit))) - continue; + if (!(cause & (1 << port_bit))) continue; phy = adapter->port[i].phy; phy_cause = phy->ops->interrupt_handler(phy); @@ -756,7 +755,7 @@ void t1_interrupts_disable(adapter_t* adapter) /* Disable PCIX & external chip interrupts. */ if (t1_is_asic(adapter)) - writel(0, adapter->regs + A_PL_ENABLE); + writel(0, adapter->regs + A_PL_ENABLE); /* PCI-X interrupts */ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0); @@ -831,11 +830,11 @@ int t1_slow_intr_handler(adapter_t *adapter) /* Power sequencing is a work-around for Intel's XPAKs. */ static void power_sequence_xpak(adapter_t* adapter) { - u32 mod_detect; - u32 gpo; + u32 mod_detect; + u32 gpo; - /* Check for XPAK */ - t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect); + /* Check for XPAK */ + t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect); if (!(ELMER0_GP_BIT5 & mod_detect)) { /* XPAK is present */ t1_tpi_read(adapter, A_ELMER0_GPO, &gpo); @@ -878,31 +877,31 @@ static int board_init(adapter_t *adapter, const struct board_info *bi) case CHBT_BOARD_N210: case CHBT_BOARD_CHT210: case CHBT_BOARD_COUGAR: - t1_tpi_par(adapter, 0xf); - t1_tpi_write(adapter, A_ELMER0_GPO, 0x800); + t1_tpi_par(adapter, 0xf); + t1_tpi_write(adapter, A_ELMER0_GPO, 0x800); break; case CHBT_BOARD_CHT110: - t1_tpi_par(adapter, 0xf); - t1_tpi_write(adapter, A_ELMER0_GPO, 0x1800); + t1_tpi_par(adapter, 0xf); + t1_tpi_write(adapter, A_ELMER0_GPO, 0x1800); - /* TBD XXX Might not need. This fixes a problem - * described in the Intel SR XPAK errata. - */ - power_sequence_xpak(adapter); + /* TBD XXX Might not need. This fixes a problem + * described in the Intel SR XPAK errata. + */ + power_sequence_xpak(adapter); break; #ifdef CONFIG_CHELSIO_T1_1G - case CHBT_BOARD_CHT204E: - /* add config space write here */ + case CHBT_BOARD_CHT204E: + /* add config space write here */ case CHBT_BOARD_CHT204: case CHBT_BOARD_CHT204V: case CHBT_BOARD_CHN204: - t1_tpi_par(adapter, 0xf); - t1_tpi_write(adapter, A_ELMER0_GPO, 0x804); - break; + t1_tpi_par(adapter, 0xf); + t1_tpi_write(adapter, A_ELMER0_GPO, 0x804); + break; case CHBT_BOARD_CHT101: case CHBT_BOARD_7500: - t1_tpi_par(adapter, 0xf); - t1_tpi_write(adapter, A_ELMER0_GPO, 0x1804); + t1_tpi_par(adapter, 0xf); + t1_tpi_write(adapter, A_ELMER0_GPO, 0x1804); break; #endif } @@ -942,7 +941,7 @@ int t1_init_hw_modules(adapter_t *adapter) goto out_err; err = 0; -out_err: + out_err: return err; } @@ -984,7 +983,7 @@ void t1_free_sw_modules(adapter_t *adapter) if (adapter->espi) t1_espi_destroy(adapter->espi); #ifdef CONFIG_CHELSIO_T1_COUGAR - if (adapter->cspi) + if (adapter->cspi) t1_cspi_destroy(adapter->cspi); #endif } @@ -1011,7 +1010,7 @@ static void __devinit init_link_config(struct link_config *lc, CH_ERR("%s: CSPI initialization failed\n", adapter->name); goto error; - } + } #endif /* diff --git a/trunk/drivers/net/chelsio/tp.c b/trunk/drivers/net/chelsio/tp.c index 6222d585e447..0ca0b6e19e43 100644 --- a/trunk/drivers/net/chelsio/tp.c +++ b/trunk/drivers/net/chelsio/tp.c @@ -17,36 +17,39 @@ struct petp { static void tp_init(adapter_t * ap, const struct tp_params *p, unsigned int tp_clk) { - u32 val; + if (t1_is_asic(ap)) { + u32 val; + + val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM | + F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET; + if (!p->pm_size) + val |= F_OFFLOAD_DISABLE; + else + val |= F_TP_IN_ESPI_CHECK_IP_CSUM | + F_TP_IN_ESPI_CHECK_TCP_CSUM; + writel(val, ap->regs + A_TP_IN_CONFIG); + writel(F_TP_OUT_CSPI_CPL | + F_TP_OUT_ESPI_ETHERNET | + F_TP_OUT_ESPI_GENERATE_IP_CSUM | + F_TP_OUT_ESPI_GENERATE_TCP_CSUM, + ap->regs + A_TP_OUT_CONFIG); + writel(V_IP_TTL(64) | + F_PATH_MTU /* IP DF bit */ | + V_5TUPLE_LOOKUP(p->use_5tuple_mode) | + V_SYN_COOKIE_PARAMETER(29), + ap->regs + A_TP_GLOBAL_CONFIG); + /* + * Enable pause frame deadlock prevention. + */ + if (is_T2(ap) && ap->params.nports > 1) { + u32 drop_ticks = DROP_MSEC * (tp_clk / 1000); + + writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR | + V_DROP_TICKS_CNT(drop_ticks) | + V_NUM_PKTS_DROPPED(DROP_PKTS_CNT), + ap->regs + A_TP_TX_DROP_CONFIG); + } - if (!t1_is_asic(ap)) - return; - - val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM | - F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET; - if (!p->pm_size) - val |= F_OFFLOAD_DISABLE; - else - val |= F_TP_IN_ESPI_CHECK_IP_CSUM | F_TP_IN_ESPI_CHECK_TCP_CSUM; - writel(val, ap->regs + A_TP_IN_CONFIG); - writel(F_TP_OUT_CSPI_CPL | - F_TP_OUT_ESPI_ETHERNET | - F_TP_OUT_ESPI_GENERATE_IP_CSUM | - F_TP_OUT_ESPI_GENERATE_TCP_CSUM, ap->regs + A_TP_OUT_CONFIG); - writel(V_IP_TTL(64) | - F_PATH_MTU /* IP DF bit */ | - V_5TUPLE_LOOKUP(p->use_5tuple_mode) | - V_SYN_COOKIE_PARAMETER(29), ap->regs + A_TP_GLOBAL_CONFIG); - /* - * Enable pause frame deadlock prevention. - */ - if (is_T2(ap) && ap->params.nports > 1) { - u32 drop_ticks = DROP_MSEC * (tp_clk / 1000); - - writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR | - V_DROP_TICKS_CNT(drop_ticks) | - V_NUM_PKTS_DROPPED(DROP_PKTS_CNT), - ap->regs + A_TP_TX_DROP_CONFIG); } } @@ -58,7 +61,6 @@ void t1_tp_destroy(struct petp *tp) struct petp *__devinit t1_tp_create(adapter_t * adapter, struct tp_params *p) { struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL); - if (!tp) return NULL; diff --git a/trunk/drivers/net/chelsio/vsc7326.c b/trunk/drivers/net/chelsio/vsc7326.c index 534ffa0f616e..85dc3b1dc309 100644 --- a/trunk/drivers/net/chelsio/vsc7326.c +++ b/trunk/drivers/net/chelsio/vsc7326.c @@ -226,21 +226,22 @@ static void run_table(adapter_t *adapter, struct init_table *ib, int len) if (ib[i].addr == INITBLOCK_SLEEP) { udelay( ib[i].data ); CH_ERR("sleep %d us\n",ib[i].data); - } else + } else { vsc_write( adapter, ib[i].addr, ib[i].data ); + } } } static int bist_rd(adapter_t *adapter, int moduleid, int address) { - int data = 0; - u32 result = 0; - - if ((address != 0x0) && - (address != 0x1) && - (address != 0x2) && - (address != 0xd) && - (address != 0xe)) + int data=0; + u32 result=0; + + if( (address != 0x0) && + (address != 0x1) && + (address != 0x2) && + (address != 0xd) && + (address != 0xe)) CH_ERR("No bist address: 0x%x\n", address); data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) | @@ -250,27 +251,27 @@ static int bist_rd(adapter_t *adapter, int moduleid, int address) udelay(10); vsc_read(adapter, REG_RAM_BIST_RESULT, &result); - if ((result & (1 << 9)) != 0x0) + if((result & (1<<9)) != 0x0) CH_ERR("Still in bist read: 0x%x\n", result); - else if ((result & (1 << 8)) != 0x0) + else if((result & (1<<8)) != 0x0) CH_ERR("bist read error: 0x%x\n", result); - return (result & 0xff); + return(result & 0xff); } static int bist_wr(adapter_t *adapter, int moduleid, int address, int value) { - int data = 0; - u32 result = 0; - - if ((address != 0x0) && - (address != 0x1) && - (address != 0x2) && - (address != 0xd) && - (address != 0xe)) + int data=0; + u32 result=0; + + if( (address != 0x0) && + (address != 0x1) && + (address != 0x2) && + (address != 0xd) && + (address != 0xe)) CH_ERR("No bist address: 0x%x\n", address); - if (value > 255) + if( value>255 ) CH_ERR("Suspicious write out of range value: 0x%x\n", value); data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) | @@ -280,12 +281,12 @@ static int bist_wr(adapter_t *adapter, int moduleid, int address, int value) udelay(5); vsc_read(adapter, REG_RAM_BIST_CMD, &result); - if ((result & (1 << 27)) != 0x0) + if((result & (1<<27)) != 0x0) CH_ERR("Still in bist write: 0x%x\n", result); - else if ((result & (1 << 26)) != 0x0) + else if((result & (1<<26)) != 0x0) CH_ERR("bist write error: 0x%x\n", result); - return 0; + return(0); } static int run_bist(adapter_t *adapter, int moduleid) @@ -294,7 +295,7 @@ static int run_bist(adapter_t *adapter, int moduleid) (void) bist_wr(adapter,moduleid, 0x00, 0x02); (void) bist_wr(adapter,moduleid, 0x01, 0x01); - return 0; + return(0); } static int check_bist(adapter_t *adapter, int moduleid) @@ -308,26 +309,27 @@ static int check_bist(adapter_t *adapter, int moduleid) if ((result & 3) != 0x3) CH_ERR("Result: 0x%x BIST error in ram %d, column: 0x%04x\n", result, moduleid, column); - return 0; + return(0); } static int enable_mem(adapter_t *adapter, int moduleid) { /*enable mem*/ (void) bist_wr(adapter,moduleid, 0x00, 0x00); - return 0; + return(0); } static int run_bist_all(adapter_t *adapter) { - int port = 0; - u32 val = 0; + int port=0; + u32 val=0; vsc_write(adapter, REG_MEM_BIST, 0x5); vsc_read(adapter, REG_MEM_BIST, &val); - for (port = 0; port < 12; port++) + for(port=0; port<12; port++){ vsc_write(adapter, REG_DEV_SETUP(port), 0x0); + } udelay(300); vsc_write(adapter, REG_SPI4_MISC, 0x00040409); @@ -350,13 +352,13 @@ static int run_bist_all(adapter_t *adapter) udelay(300); vsc_write(adapter, REG_SPI4_MISC, 0x60040400); udelay(300); - for (port = 0; port < 12; port++) + for(port=0; port<12; port++){ vsc_write(adapter, REG_DEV_SETUP(port), 0x1); - + } udelay(300); vsc_write(adapter, REG_MEM_BIST, 0x0); mdelay(10); - return 0; + return(0); } static int mac_intr_handler(struct cmac *mac) @@ -589,46 +591,40 @@ static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat) static void port_stats_update(struct cmac *mac) { - struct { - unsigned int reg; - unsigned int offset; - } hw_stats[] = { - -#define HW_STAT(reg, stat_name) \ - { reg, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL } - - /* Rx stats */ - HW_STAT(RxUnicast, RxUnicastFramesOK), - HW_STAT(RxMulticast, RxMulticastFramesOK), - HW_STAT(RxBroadcast, RxBroadcastFramesOK), - HW_STAT(Crc, RxFCSErrors), - HW_STAT(RxAlignment, RxAlignErrors), - HW_STAT(RxOversize, RxFrameTooLongErrors), - HW_STAT(RxPause, RxPauseFrames), - HW_STAT(RxJabbers, RxJabberErrors), - HW_STAT(RxFragments, RxRuntErrors), - HW_STAT(RxUndersize, RxRuntErrors), - HW_STAT(RxSymbolCarrier, RxSymbolErrors), - HW_STAT(RxSize1519ToMax, RxJumboFramesOK), - - /* Tx stats (skip collision stats as we are full-duplex only) */ - HW_STAT(TxUnicast, TxUnicastFramesOK), - HW_STAT(TxMulticast, TxMulticastFramesOK), - HW_STAT(TxBroadcast, TxBroadcastFramesOK), - HW_STAT(TxPause, TxPauseFrames), - HW_STAT(TxUnderrun, TxUnderrun), - HW_STAT(TxSize1519ToMax, TxJumboFramesOK), - }, *p = hw_stats; - unsigned int port = mac->instance->index; - u64 *stats = (u64 *)&mac->stats; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(hw_stats); i++) - rmon_update(mac, CRA(0x4, port, p->reg), stats + p->offset); + int port = mac->instance->index; - rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK); + /* Rx stats */ rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK); rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad); + rmon_update(mac, REG_RX_UNICAST(port), &mac->stats.RxUnicastFramesOK); + rmon_update(mac, REG_RX_MULTICAST(port), + &mac->stats.RxMulticastFramesOK); + rmon_update(mac, REG_RX_BROADCAST(port), + &mac->stats.RxBroadcastFramesOK); + rmon_update(mac, REG_CRC(port), &mac->stats.RxFCSErrors); + rmon_update(mac, REG_RX_ALIGNMENT(port), &mac->stats.RxAlignErrors); + rmon_update(mac, REG_RX_OVERSIZE(port), + &mac->stats.RxFrameTooLongErrors); + rmon_update(mac, REG_RX_PAUSE(port), &mac->stats.RxPauseFrames); + rmon_update(mac, REG_RX_JABBERS(port), &mac->stats.RxJabberErrors); + rmon_update(mac, REG_RX_FRAGMENTS(port), &mac->stats.RxRuntErrors); + rmon_update(mac, REG_RX_UNDERSIZE(port), &mac->stats.RxRuntErrors); + rmon_update(mac, REG_RX_SYMBOL_CARRIER(port), + &mac->stats.RxSymbolErrors); + rmon_update(mac, REG_RX_SIZE_1519_TO_MAX(port), + &mac->stats.RxJumboFramesOK); + + /* Tx stats (skip collision stats as we are full-duplex only) */ + rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK); + rmon_update(mac, REG_TX_UNICAST(port), &mac->stats.TxUnicastFramesOK); + rmon_update(mac, REG_TX_MULTICAST(port), + &mac->stats.TxMulticastFramesOK); + rmon_update(mac, REG_TX_BROADCAST(port), + &mac->stats.TxBroadcastFramesOK); + rmon_update(mac, REG_TX_PAUSE(port), &mac->stats.TxPauseFrames); + rmon_update(mac, REG_TX_UNDERRUN(port), &mac->stats.TxUnderrun); + rmon_update(mac, REG_TX_SIZE_1519_TO_MAX(port), + &mac->stats.TxJumboFramesOK); } /* @@ -690,8 +686,7 @@ static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index) int i; mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL); - if (!mac) - return NULL; + if (!mac) return NULL; mac->ops = &vsc7326_ops; mac->instance = (cmac_instance *)(mac + 1); diff --git a/trunk/drivers/net/chelsio/vsc7326_reg.h b/trunk/drivers/net/chelsio/vsc7326_reg.h index 479edbcabe68..491bcf75c4fb 100644 --- a/trunk/drivers/net/chelsio/vsc7326_reg.h +++ b/trunk/drivers/net/chelsio/vsc7326_reg.h @@ -192,84 +192,73 @@ #define REG_HDX(pn) CRA(0x1,pn,0x19) /* Half-duplex config */ /* Statistics */ -/* CRA(0x4,pn,reg) */ -/* reg below */ /* pn = port number, 0-a, a = 10GbE */ +#define REG_RX_IN_BYTES(pn) CRA(0x4,pn,0x00) /* # Rx in octets */ +#define REG_RX_SYMBOL_CARRIER(pn) CRA(0x4,pn,0x01) /* Frames w/ symbol errors */ +#define REG_RX_PAUSE(pn) CRA(0x4,pn,0x02) /* # pause frames received */ +#define REG_RX_UNSUP_OPCODE(pn) CRA(0x4,pn,0x03) /* # control frames with unsupported opcode */ +#define REG_RX_OK_BYTES(pn) CRA(0x4,pn,0x04) /* # octets in good frames */ +#define REG_RX_BAD_BYTES(pn) CRA(0x4,pn,0x05) /* # octets in bad frames */ +#define REG_RX_UNICAST(pn) CRA(0x4,pn,0x06) /* # good unicast frames */ +#define REG_RX_MULTICAST(pn) CRA(0x4,pn,0x07) /* # good multicast frames */ +#define REG_RX_BROADCAST(pn) CRA(0x4,pn,0x08) /* # good broadcast frames */ +#define REG_CRC(pn) CRA(0x4,pn,0x09) /* # frames w/ bad CRC only */ +#define REG_RX_ALIGNMENT(pn) CRA(0x4,pn,0x0a) /* # frames w/ alignment err */ +#define REG_RX_UNDERSIZE(pn) CRA(0x4,pn,0x0b) /* # frames undersize */ +#define REG_RX_FRAGMENTS(pn) CRA(0x4,pn,0x0c) /* # frames undersize w/ crc err */ +#define REG_RX_IN_RANGE_LENGTH_ERROR(pn) CRA(0x4,pn,0x0d) /* # frames with length error */ +#define REG_RX_OUT_OF_RANGE_ERROR(pn) CRA(0x4,pn,0x0e) /* # frames with illegal length field */ +#define REG_RX_OVERSIZE(pn) CRA(0x4,pn,0x0f) /* # frames oversize */ +#define REG_RX_JABBERS(pn) CRA(0x4,pn,0x10) /* # frames oversize w/ crc err */ +#define REG_RX_SIZE_64(pn) CRA(0x4,pn,0x11) /* # frames 64 octets long */ +#define REG_RX_SIZE_65_TO_127(pn) CRA(0x4,pn,0x12) /* # frames 65-127 octets */ +#define REG_RX_SIZE_128_TO_255(pn) CRA(0x4,pn,0x13) /* # frames 128-255 */ +#define REG_RX_SIZE_256_TO_511(pn) CRA(0x4,pn,0x14) /* # frames 256-511 */ +#define REG_RX_SIZE_512_TO_1023(pn) CRA(0x4,pn,0x15) /* # frames 512-1023 */ +#define REG_RX_SIZE_1024_TO_1518(pn) CRA(0x4,pn,0x16) /* # frames 1024-1518 */ +#define REG_RX_SIZE_1519_TO_MAX(pn) CRA(0x4,pn,0x17) /* # frames 1519-max */ -enum { - RxInBytes = 0x00, // # Rx in octets - RxSymbolCarrier = 0x01, // Frames w/ symbol errors - RxPause = 0x02, // # pause frames received - RxUnsupOpcode = 0x03, // # control frames with unsupported opcode - RxOkBytes = 0x04, // # octets in good frames - RxBadBytes = 0x05, // # octets in bad frames - RxUnicast = 0x06, // # good unicast frames - RxMulticast = 0x07, // # good multicast frames - RxBroadcast = 0x08, // # good broadcast frames - Crc = 0x09, // # frames w/ bad CRC only - RxAlignment = 0x0a, // # frames w/ alignment err - RxUndersize = 0x0b, // # frames undersize - RxFragments = 0x0c, // # frames undersize w/ crc err - RxInRangeLengthError = 0x0d, // # frames with length error - RxOutOfRangeError = 0x0e, // # frames with illegal length field - RxOversize = 0x0f, // # frames oversize - RxJabbers = 0x10, // # frames oversize w/ crc err - RxSize64 = 0x11, // # frames 64 octets long - RxSize65To127 = 0x12, // # frames 65-127 octets - RxSize128To255 = 0x13, // # frames 128-255 - RxSize256To511 = 0x14, // # frames 256-511 - RxSize512To1023 = 0x15, // # frames 512-1023 - RxSize1024To1518 = 0x16, // # frames 1024-1518 - RxSize1519ToMax = 0x17, // # frames 1519-max +#define REG_TX_OUT_BYTES(pn) CRA(0x4,pn,0x18) /* # octets tx */ +#define REG_TX_PAUSE(pn) CRA(0x4,pn,0x19) /* # pause frames sent */ +#define REG_TX_OK_BYTES(pn) CRA(0x4,pn,0x1a) /* # octets tx OK */ +#define REG_TX_UNICAST(pn) CRA(0x4,pn,0x1b) /* # frames unicast */ +#define REG_TX_MULTICAST(pn) CRA(0x4,pn,0x1c) /* # frames multicast */ +#define REG_TX_BROADCAST(pn) CRA(0x4,pn,0x1d) /* # frames broadcast */ +#define REG_TX_MULTIPLE_COLL(pn) CRA(0x4,pn,0x1e) /* # frames tx after multiple collisions */ +#define REG_TX_LATE_COLL(pn) CRA(0x4,pn,0x1f) /* # late collisions detected */ +#define REG_TX_XCOLL(pn) CRA(0x4,pn,0x20) /* # frames lost, excessive collisions */ +#define REG_TX_DEFER(pn) CRA(0x4,pn,0x21) /* # frames deferred on first tx attempt */ +#define REG_TX_XDEFER(pn) CRA(0x4,pn,0x22) /* # frames excessively deferred */ +#define REG_TX_CSENSE(pn) CRA(0x4,pn,0x23) /* carrier sense errors at frame end */ +#define REG_TX_SIZE_64(pn) CRA(0x4,pn,0x24) /* # frames 64 octets long */ +#define REG_TX_SIZE_65_TO_127(pn) CRA(0x4,pn,0x25) /* # frames 65-127 octets */ +#define REG_TX_SIZE_128_TO_255(pn) CRA(0x4,pn,0x26) /* # frames 128-255 */ +#define REG_TX_SIZE_256_TO_511(pn) CRA(0x4,pn,0x27) /* # frames 256-511 */ +#define REG_TX_SIZE_512_TO_1023(pn) CRA(0x4,pn,0x28) /* # frames 512-1023 */ +#define REG_TX_SIZE_1024_TO_1518(pn) CRA(0x4,pn,0x29) /* # frames 1024-1518 */ +#define REG_TX_SIZE_1519_TO_MAX(pn) CRA(0x4,pn,0x2a) /* # frames 1519-max */ +#define REG_TX_SINGLE_COLL(pn) CRA(0x4,pn,0x2b) /* # frames tx after single collision */ +#define REG_TX_BACKOFF2(pn) CRA(0x4,pn,0x2c) /* # frames tx ok after 2 backoffs/collisions */ +#define REG_TX_BACKOFF3(pn) CRA(0x4,pn,0x2d) /* after 3 backoffs/collisions */ +#define REG_TX_BACKOFF4(pn) CRA(0x4,pn,0x2e) /* after 4 */ +#define REG_TX_BACKOFF5(pn) CRA(0x4,pn,0x2f) /* after 5 */ +#define REG_TX_BACKOFF6(pn) CRA(0x4,pn,0x30) /* after 6 */ +#define REG_TX_BACKOFF7(pn) CRA(0x4,pn,0x31) /* after 7 */ +#define REG_TX_BACKOFF8(pn) CRA(0x4,pn,0x32) /* after 8 */ +#define REG_TX_BACKOFF9(pn) CRA(0x4,pn,0x33) /* after 9 */ +#define REG_TX_BACKOFF10(pn) CRA(0x4,pn,0x34) /* after 10 */ +#define REG_TX_BACKOFF11(pn) CRA(0x4,pn,0x35) /* after 11 */ +#define REG_TX_BACKOFF12(pn) CRA(0x4,pn,0x36) /* after 12 */ +#define REG_TX_BACKOFF13(pn) CRA(0x4,pn,0x37) /* after 13 */ +#define REG_TX_BACKOFF14(pn) CRA(0x4,pn,0x38) /* after 14 */ +#define REG_TX_BACKOFF15(pn) CRA(0x4,pn,0x39) /* after 15 */ +#define REG_TX_UNDERRUN(pn) CRA(0x4,pn,0x3a) /* # frames dropped from underrun */ +#define REG_RX_XGMII_PROT_ERR CRA(0x4,0xa,0x3b) /* # protocol errors detected on XGMII interface */ +#define REG_RX_IPG_SHRINK(pn) CRA(0x4,pn,0x3c) /* # of IPG shrinks detected */ - TxOutBytes = 0x18, // # octets tx - TxPause = 0x19, // # pause frames sent - TxOkBytes = 0x1a, // # octets tx OK - TxUnicast = 0x1b, // # frames unicast - TxMulticast = 0x1c, // # frames multicast - TxBroadcast = 0x1d, // # frames broadcast - TxMultipleColl = 0x1e, // # frames tx after multiple collisions - TxLateColl = 0x1f, // # late collisions detected - TxXcoll = 0x20, // # frames lost, excessive collisions - TxDefer = 0x21, // # frames deferred on first tx attempt - TxXdefer = 0x22, // # frames excessively deferred - TxCsense = 0x23, // carrier sense errors at frame end - TxSize64 = 0x24, // # frames 64 octets long - TxSize65To127 = 0x25, // # frames 65-127 octets - TxSize128To255 = 0x26, // # frames 128-255 - TxSize256To511 = 0x27, // # frames 256-511 - TxSize512To1023 = 0x28, // # frames 512-1023 - TxSize1024To1518 = 0x29, // # frames 1024-1518 - TxSize1519ToMax = 0x2a, // # frames 1519-max - TxSingleColl = 0x2b, // # frames tx after single collision - TxBackoff2 = 0x2c, // # frames tx ok after 2 backoffs/collisions - TxBackoff3 = 0x2d, // after 3 backoffs/collisions - TxBackoff4 = 0x2e, // after 4 - TxBackoff5 = 0x2f, // after 5 - TxBackoff6 = 0x30, // after 6 - TxBackoff7 = 0x31, // after 7 - TxBackoff8 = 0x32, // after 8 - TxBackoff9 = 0x33, // after 9 - TxBackoff10 = 0x34, // after 10 - TxBackoff11 = 0x35, // after 11 - TxBackoff12 = 0x36, // after 12 - TxBackoff13 = 0x37, // after 13 - TxBackoff14 = 0x38, // after 14 - TxBackoff15 = 0x39, // after 15 - TxUnderrun = 0x3a, // # frames dropped from underrun - // Hole. See REG_RX_XGMII_PROT_ERR below. - RxIpgShrink = 0x3c, // # of IPG shrinks detected - // Duplicate. See REG_STAT_STICKY10G below. - StatSticky1G = 0x3e, // tri-speed sticky bits - StatInit = 0x3f // Clear all statistics -}; - -#define REG_RX_XGMII_PROT_ERR CRA(0x4,0xa,0x3b) /* # protocol errors detected on XGMII interface */ -#define REG_STAT_STICKY10G CRA(0x4,0xa,StatSticky1G) /* 10GbE sticky bits */ - -#define REG_RX_OK_BYTES(pn) CRA(0x4,pn,RxOkBytes) -#define REG_RX_BAD_BYTES(pn) CRA(0x4,pn,RxBadBytes) -#define REG_TX_OK_BYTES(pn) CRA(0x4,pn,TxOkBytes) +#define REG_STAT_STICKY1G(pn) CRA(0x4,pn,0x3e) /* tri-speed sticky bits */ +#define REG_STAT_STICKY10G CRA(0x4,0xa,0x3e) /* 10GbE sticky bits */ +#define REG_STAT_INIT(pn) CRA(0x4,pn,0x3f) /* Clear all statistics */ /* MII-Management Block registers */ /* These are for MII-M interface 0, which is the bidirectional LVTTL one. If diff --git a/trunk/drivers/net/chelsio/vsc8244.c b/trunk/drivers/net/chelsio/vsc8244.c index 251d4859c91d..c493e783d459 100644 --- a/trunk/drivers/net/chelsio/vsc8244.c +++ b/trunk/drivers/net/chelsio/vsc8244.c @@ -54,7 +54,7 @@ enum { }; #define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \ - VSC_INTR_NEG_DONE) + VSC_INTR_NEG_DONE) #define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \ VSC_INTR_ENABLE) @@ -94,18 +94,19 @@ static int vsc8244_intr_enable(struct cphy *cphy) { simple_mdio_write(cphy, VSC8244_INTR_ENABLE, INTR_MASK); - /* Enable interrupts through Elmer */ + /* Enable interrupts through Elmer */ if (t1_is_asic(cphy->adapter)) { u32 elmer; t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); elmer |= ELMER0_GP_BIT1; - if (is_T2(cphy->adapter)) + if (is_T2(cphy->adapter)) { elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4; + } t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); } - return 0; + return 0; } static int vsc8244_intr_disable(struct cphy *cphy) @@ -117,18 +118,19 @@ static int vsc8244_intr_disable(struct cphy *cphy) t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); elmer &= ~ELMER0_GP_BIT1; - if (is_T2(cphy->adapter)) + if (is_T2(cphy->adapter)) { elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4); + } t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); } - return 0; + return 0; } static int vsc8244_intr_clear(struct cphy *cphy) { u32 val; - u32 elmer; + u32 elmer; /* Clear PHY interrupts by reading the register. */ simple_mdio_read(cphy, VSC8244_INTR_ENABLE, &val); @@ -136,12 +138,13 @@ static int vsc8244_intr_clear(struct cphy *cphy) if (t1_is_asic(cphy->adapter)) { t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer); elmer |= ELMER0_GP_BIT1; - if (is_T2(cphy->adapter)) + if (is_T2(cphy->adapter)) { elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4; + } t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer); } - return 0; + return 0; } /* @@ -176,13 +179,13 @@ static int vsc8244_set_speed_duplex(struct cphy *phy, int speed, int duplex) int t1_mdio_set_bits(struct cphy *phy, int mmd, int reg, unsigned int bits) { - int ret; - unsigned int val; + int ret; + unsigned int val; - ret = mdio_read(phy, mmd, reg, &val); - if (!ret) - ret = mdio_write(phy, mmd, reg, val | bits); - return ret; + ret = mdio_read(phy, mmd, reg, &val); + if (!ret) + ret = mdio_write(phy, mmd, reg, val | bits); + return ret; } static int vsc8244_autoneg_enable(struct cphy *cphy) @@ -232,7 +235,7 @@ static int vsc8244_advertise(struct cphy *phy, unsigned int advertise_map) } static int vsc8244_get_link_status(struct cphy *cphy, int *link_ok, - int *speed, int *duplex, int *fc) + int *speed, int *duplex, int *fc) { unsigned int bmcr, status, lpa, adv; int err, sp = -1, dplx = -1, pause = 0; @@ -340,13 +343,11 @@ static struct cphy_ops vsc8244_ops = { .get_link_status = vsc8244_get_link_status }; -static struct cphy* vsc8244_phy_create(adapter_t *adapter, int phy_addr, - struct mdio_ops *mdio_ops) +static struct cphy* vsc8244_phy_create(adapter_t *adapter, int phy_addr, struct mdio_ops *mdio_ops) { struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL); - if (!cphy) - return NULL; + if (!cphy) return NULL; cphy_init(cphy, adapter, phy_addr, &vsc8244_ops, mdio_ops); diff --git a/trunk/drivers/net/cxgb3/Makefile b/trunk/drivers/net/cxgb3/Makefile deleted file mode 100644 index 343467985321..000000000000 --- a/trunk/drivers/net/cxgb3/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Chelsio T3 driver -# - -obj-$(CONFIG_CHELSIO_T3) += cxgb3.o - -cxgb3-objs := cxgb3_main.o ael1002.o vsc8211.o t3_hw.o mc5.o \ - xgmac.o sge.o l2t.o cxgb3_offload.o diff --git a/trunk/drivers/net/cxgb3/adapter.h b/trunk/drivers/net/cxgb3/adapter.h deleted file mode 100644 index 5c97a64451ce..000000000000 --- a/trunk/drivers/net/cxgb3/adapter.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* This file should not be included directly. Include common.h instead. */ - -#ifndef __T3_ADAPTER_H__ -#define __T3_ADAPTER_H__ - -#include -#include -#include -#include -#include -#include -#include "t3cdev.h" -#include -#include -#include - -typedef irqreturn_t(*intr_handler_t) (int, void *); - -struct vlan_group; - -struct port_info { - struct vlan_group *vlan_grp; - const struct port_type_info *port_type; - u8 port_id; - u8 rx_csum_offload; - u8 nqsets; - u8 first_qset; - struct cphy phy; - struct cmac mac; - struct link_config link_config; - struct net_device_stats netstats; - int activity; -}; - -enum { /* adapter flags */ - FULL_INIT_DONE = (1 << 0), - USING_MSI = (1 << 1), - USING_MSIX = (1 << 2), - QUEUES_BOUND = (1 << 3), -}; - -struct rx_desc; -struct rx_sw_desc; - -struct sge_fl { /* SGE per free-buffer list state */ - unsigned int buf_size; /* size of each Rx buffer */ - unsigned int credits; /* # of available Rx buffers */ - unsigned int size; /* capacity of free list */ - unsigned int cidx; /* consumer index */ - unsigned int pidx; /* producer index */ - unsigned int gen; /* free list generation */ - struct rx_desc *desc; /* address of HW Rx descriptor ring */ - struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ - dma_addr_t phys_addr; /* physical address of HW ring start */ - unsigned int cntxt_id; /* SGE context id for the free list */ - unsigned long empty; /* # of times queue ran out of buffers */ -}; - -/* - * Bundle size for grouping offload RX packets for delivery to the stack. - * Don't make this too big as we do prefetch on each packet in a bundle. - */ -# define RX_BUNDLE_SIZE 8 - -struct rsp_desc; - -struct sge_rspq { /* state for an SGE response queue */ - unsigned int credits; /* # of pending response credits */ - unsigned int size; /* capacity of response queue */ - unsigned int cidx; /* consumer index */ - unsigned int gen; /* current generation bit */ - unsigned int polling; /* is the queue serviced through NAPI? */ - unsigned int holdoff_tmr; /* interrupt holdoff timer in 100ns */ - unsigned int next_holdoff; /* holdoff time for next interrupt */ - struct rsp_desc *desc; /* address of HW response ring */ - dma_addr_t phys_addr; /* physical address of the ring */ - unsigned int cntxt_id; /* SGE context id for the response q */ - spinlock_t lock; /* guards response processing */ - struct sk_buff *rx_head; /* offload packet receive queue head */ - struct sk_buff *rx_tail; /* offload packet receive queue tail */ - - unsigned long offload_pkts; - unsigned long offload_bundles; - unsigned long eth_pkts; /* # of ethernet packets */ - unsigned long pure_rsps; /* # of pure (non-data) responses */ - unsigned long imm_data; /* responses with immediate data */ - unsigned long rx_drops; /* # of packets dropped due to no mem */ - unsigned long async_notif; /* # of asynchronous notification events */ - unsigned long empty; /* # of times queue ran out of credits */ - unsigned long nomem; /* # of responses deferred due to no mem */ - unsigned long unhandled_irqs; /* # of spurious intrs */ -}; - -struct tx_desc; -struct tx_sw_desc; - -struct sge_txq { /* state for an SGE Tx queue */ - unsigned long flags; /* HW DMA fetch status */ - unsigned int in_use; /* # of in-use Tx descriptors */ - unsigned int size; /* # of descriptors */ - unsigned int processed; /* total # of descs HW has processed */ - unsigned int cleaned; /* total # of descs SW has reclaimed */ - unsigned int stop_thres; /* SW TX queue suspend threshold */ - unsigned int cidx; /* consumer index */ - unsigned int pidx; /* producer index */ - unsigned int gen; /* current value of generation bit */ - unsigned int unacked; /* Tx descriptors used since last COMPL */ - struct tx_desc *desc; /* address of HW Tx descriptor ring */ - struct tx_sw_desc *sdesc; /* address of SW Tx descriptor ring */ - spinlock_t lock; /* guards enqueueing of new packets */ - unsigned int token; /* WR token */ - dma_addr_t phys_addr; /* physical address of the ring */ - struct sk_buff_head sendq; /* List of backpressured offload packets */ - struct tasklet_struct qresume_tsk; /* restarts the queue */ - unsigned int cntxt_id; /* SGE context id for the Tx q */ - unsigned long stops; /* # of times q has been stopped */ - unsigned long restarts; /* # of queue restarts */ -}; - -enum { /* per port SGE statistics */ - SGE_PSTAT_TSO, /* # of TSO requests */ - SGE_PSTAT_RX_CSUM_GOOD, /* # of successful RX csum offloads */ - SGE_PSTAT_TX_CSUM, /* # of TX checksum offloads */ - SGE_PSTAT_VLANEX, /* # of VLAN tag extractions */ - SGE_PSTAT_VLANINS, /* # of VLAN tag insertions */ - - SGE_PSTAT_MAX /* must be last */ -}; - -struct sge_qset { /* an SGE queue set */ - struct sge_rspq rspq; - struct sge_fl fl[SGE_RXQ_PER_SET]; - struct sge_txq txq[SGE_TXQ_PER_SET]; - struct net_device *netdev; /* associated net device */ - unsigned long txq_stopped; /* which Tx queues are stopped */ - struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ - unsigned long port_stats[SGE_PSTAT_MAX]; -} ____cacheline_aligned; - -struct sge { - struct sge_qset qs[SGE_QSETS]; - spinlock_t reg_lock; /* guards non-atomic SGE registers (eg context) */ -}; - -struct adapter { - struct t3cdev tdev; - struct list_head adapter_list; - void __iomem *regs; - struct pci_dev *pdev; - unsigned long registered_device_map; - unsigned long open_device_map; - unsigned long flags; - - const char *name; - int msg_enable; - unsigned int mmio_len; - - struct adapter_params params; - unsigned int slow_intr_mask; - unsigned long irq_stats[IRQ_NUM_STATS]; - - struct { - unsigned short vec; - char desc[22]; - } msix_info[SGE_QSETS + 1]; - - /* T3 modules */ - struct sge sge; - struct mc7 pmrx; - struct mc7 pmtx; - struct mc7 cm; - struct mc5 mc5; - - struct net_device *port[MAX_NPORTS]; - unsigned int check_task_cnt; - struct delayed_work adap_check_task; - struct work_struct ext_intr_handler_task; - - /* - * Dummy netdevices are needed when using multiple receive queues with - * NAPI as each netdevice can service only one queue. - */ - struct net_device *dummy_netdev[SGE_QSETS - 1]; - - struct dentry *debugfs_root; - - struct mutex mdio_lock; - spinlock_t stats_lock; - spinlock_t work_lock; -}; - -static inline u32 t3_read_reg(struct adapter *adapter, u32 reg_addr) -{ - u32 val = readl(adapter->regs + reg_addr); - - CH_DBG(adapter, MMIO, "read register 0x%x value 0x%x\n", reg_addr, val); - return val; -} - -static inline void t3_write_reg(struct adapter *adapter, u32 reg_addr, u32 val) -{ - CH_DBG(adapter, MMIO, "setting register 0x%x to 0x%x\n", reg_addr, val); - writel(val, adapter->regs + reg_addr); -} - -static inline struct port_info *adap2pinfo(struct adapter *adap, int idx) -{ - return netdev_priv(adap->port[idx]); -} - -/* - * We use the spare atalk_ptr to map a net device to its SGE queue set. - * This is a macro so it can be used as l-value. - */ -#define dev2qset(netdev) ((netdev)->atalk_ptr) - -#define OFFLOAD_DEVMAP_BIT 15 - -#define tdev2adap(d) container_of(d, struct adapter, tdev) - -static inline int offload_running(struct adapter *adapter) -{ - return test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map); -} - -int t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb); - -void t3_os_ext_intr_handler(struct adapter *adapter); -void t3_os_link_changed(struct adapter *adapter, int port_id, int link_status, - int speed, int duplex, int fc); - -void t3_sge_start(struct adapter *adap); -void t3_sge_stop(struct adapter *adap); -void t3_free_sge_resources(struct adapter *adap); -void t3_sge_err_intr_handler(struct adapter *adapter); -intr_handler_t t3_intr_handler(struct adapter *adap, int polling); -int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev); -int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb); -void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p); -int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, - int irq_vec_idx, const struct qset_params *p, - int ntxq, struct net_device *netdev); -int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx, - unsigned char *data); -irqreturn_t t3_sge_intr_msix(int irq, void *cookie); - -#endif /* __T3_ADAPTER_H__ */ diff --git a/trunk/drivers/net/cxgb3/ael1002.c b/trunk/drivers/net/cxgb3/ael1002.c deleted file mode 100644 index 73a41e6a5bfc..000000000000 --- a/trunk/drivers/net/cxgb3/ael1002.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "common.h" -#include "regs.h" - -enum { - AEL100X_TX_DISABLE = 9, - AEL100X_TX_CONFIG1 = 0xc002, - AEL1002_PWR_DOWN_HI = 0xc011, - AEL1002_PWR_DOWN_LO = 0xc012, - AEL1002_XFI_EQL = 0xc015, - AEL1002_LB_EN = 0xc017, - - LASI_CTRL = 0x9002, - LASI_STAT = 0x9005 -}; - -static void ael100x_txon(struct cphy *phy) -{ - int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; - - msleep(100); - t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio); - msleep(30); -} - -static int ael1002_power_down(struct cphy *phy, int enable) -{ - int err; - - err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable); - if (!err) - err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, - BMCR_PDOWN, enable ? BMCR_PDOWN : 0); - return err; -} - -static int ael1002_reset(struct cphy *phy, int wait) -{ - int err; - - if ((err = ael1002_power_down(phy, 0)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) || - (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) || - (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN, - 0, 1 << 5))) - return err; - return 0; -} - -static int ael1002_intr_noop(struct cphy *phy) -{ - return 0; -} - -static int ael100x_get_link_status(struct cphy *phy, int *link_ok, - int *speed, int *duplex, int *fc) -{ - if (link_ok) { - unsigned int status; - int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status); - - /* - * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it - * once more to get the current link state. - */ - if (!err && !(status & BMSR_LSTATUS)) - err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, - &status); - if (err) - return err; - *link_ok = !!(status & BMSR_LSTATUS); - } - if (speed) - *speed = SPEED_10000; - if (duplex) - *duplex = DUPLEX_FULL; - return 0; -} - -static struct cphy_ops ael1002_ops = { - .reset = ael1002_reset, - .intr_enable = ael1002_intr_noop, - .intr_disable = ael1002_intr_noop, - .intr_clear = ael1002_intr_noop, - .intr_handler = ael1002_intr_noop, - .get_link_status = ael100x_get_link_status, - .power_down = ael1002_power_down, -}; - -void t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *mdio_ops) -{ - cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops); - ael100x_txon(phy); -} - -static int ael1006_reset(struct cphy *phy, int wait) -{ - return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); -} - -static int ael1006_intr_enable(struct cphy *phy) -{ - return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1); -} - -static int ael1006_intr_disable(struct cphy *phy) -{ - return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0); -} - -static int ael1006_intr_clear(struct cphy *phy) -{ - u32 val; - - return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val); -} - -static int ael1006_intr_handler(struct cphy *phy) -{ - unsigned int status; - int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status); - - if (err) - return err; - return (status & 1) ? cphy_cause_link_change : 0; -} - -static int ael1006_power_down(struct cphy *phy, int enable) -{ - return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, - BMCR_PDOWN, enable ? BMCR_PDOWN : 0); -} - -static struct cphy_ops ael1006_ops = { - .reset = ael1006_reset, - .intr_enable = ael1006_intr_enable, - .intr_disable = ael1006_intr_disable, - .intr_clear = ael1006_intr_clear, - .intr_handler = ael1006_intr_handler, - .get_link_status = ael100x_get_link_status, - .power_down = ael1006_power_down, -}; - -void t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *mdio_ops) -{ - cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops); - ael100x_txon(phy); -} - -static struct cphy_ops qt2045_ops = { - .reset = ael1006_reset, - .intr_enable = ael1006_intr_enable, - .intr_disable = ael1006_intr_disable, - .intr_clear = ael1006_intr_clear, - .intr_handler = ael1006_intr_handler, - .get_link_status = ael100x_get_link_status, - .power_down = ael1006_power_down, -}; - -void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *mdio_ops) -{ - unsigned int stat; - - cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops); - - /* - * Some cards where the PHY is supposed to be at address 0 actually - * have it at 1. - */ - if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && - stat == 0xffff) - phy->addr = 1; -} - -static int xaui_direct_reset(struct cphy *phy, int wait) -{ - return 0; -} - -static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, - int *speed, int *duplex, int *fc) -{ - if (link_ok) { - unsigned int status; - - status = t3_read_reg(phy->adapter, - XGM_REG(A_XGM_SERDES_STAT0, phy->addr)); - *link_ok = !(status & F_LOWSIG0); - } - if (speed) - *speed = SPEED_10000; - if (duplex) - *duplex = DUPLEX_FULL; - return 0; -} - -static int xaui_direct_power_down(struct cphy *phy, int enable) -{ - return 0; -} - -static struct cphy_ops xaui_direct_ops = { - .reset = xaui_direct_reset, - .intr_enable = ael1002_intr_noop, - .intr_disable = ael1002_intr_noop, - .intr_clear = ael1002_intr_noop, - .intr_handler = ael1002_intr_noop, - .get_link_status = xaui_direct_get_link_status, - .power_down = xaui_direct_power_down, -}; - -void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *mdio_ops) -{ - cphy_init(phy, adapter, 1, &xaui_direct_ops, mdio_ops); -} diff --git a/trunk/drivers/net/cxgb3/common.h b/trunk/drivers/net/cxgb3/common.h deleted file mode 100644 index e23deeb7d06d..000000000000 --- a/trunk/drivers/net/cxgb3/common.h +++ /dev/null @@ -1,729 +0,0 @@ -/* - * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef __CHELSIO_COMMON_H -#define __CHELSIO_COMMON_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" - -#define CH_ERR(adap, fmt, ...) dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__) -#define CH_WARN(adap, fmt, ...) dev_warn(&adap->pdev->dev, fmt, ## __VA_ARGS__) -#define CH_ALERT(adap, fmt, ...) \ - dev_printk(KERN_ALERT, &adap->pdev->dev, fmt, ## __VA_ARGS__) - -/* - * More powerful macro that selectively prints messages based on msg_enable. - * For info and debugging messages. - */ -#define CH_MSG(adapter, level, category, fmt, ...) do { \ - if ((adapter)->msg_enable & NETIF_MSG_##category) \ - dev_printk(KERN_##level, &adapter->pdev->dev, fmt, \ - ## __VA_ARGS__); \ -} while (0) - -#ifdef DEBUG -# define CH_DBG(adapter, category, fmt, ...) \ - CH_MSG(adapter, DEBUG, category, fmt, ## __VA_ARGS__) -#else -# define CH_DBG(adapter, category, fmt, ...) -#endif - -/* Additional NETIF_MSG_* categories */ -#define NETIF_MSG_MMIO 0x8000000 - -struct t3_rx_mode { - struct net_device *dev; - struct dev_mc_list *mclist; - unsigned int idx; -}; - -static inline void init_rx_mode(struct t3_rx_mode *p, struct net_device *dev, - struct dev_mc_list *mclist) -{ - p->dev = dev; - p->mclist = mclist; - p->idx = 0; -} - -static inline u8 *t3_get_next_mcaddr(struct t3_rx_mode *rm) -{ - u8 *addr = NULL; - - if (rm->mclist && rm->idx < rm->dev->mc_count) { - addr = rm->mclist->dmi_addr; - rm->mclist = rm->mclist->next; - rm->idx++; - } - return addr; -} - -enum { - MAX_NPORTS = 2, /* max # of ports */ - MAX_FRAME_SIZE = 10240, /* max MAC frame size, including header + FCS */ - EEPROMSIZE = 8192, /* Serial EEPROM size */ - RSS_TABLE_SIZE = 64, /* size of RSS lookup and mapping tables */ - TCB_SIZE = 128, /* TCB size */ - NMTUS = 16, /* size of MTU table */ - NCCTRL_WIN = 32, /* # of congestion control windows */ -}; - -#define MAX_RX_COALESCING_LEN 16224U - -enum { - PAUSE_RX = 1 << 0, - PAUSE_TX = 1 << 1, - PAUSE_AUTONEG = 1 << 2 -}; - -enum { - SUPPORTED_OFFLOAD = 1 << 24, - SUPPORTED_IRQ = 1 << 25 -}; - -enum { /* adapter interrupt-maintained statistics */ - STAT_ULP_CH0_PBL_OOB, - STAT_ULP_CH1_PBL_OOB, - STAT_PCI_CORR_ECC, - - IRQ_NUM_STATS /* keep last */ -}; - -enum { - SGE_QSETS = 8, /* # of SGE Tx/Rx/RspQ sets */ - SGE_RXQ_PER_SET = 2, /* # of Rx queues per set */ - SGE_TXQ_PER_SET = 3 /* # of Tx queues per set */ -}; - -enum sge_context_type { /* SGE egress context types */ - SGE_CNTXT_RDMA = 0, - SGE_CNTXT_ETH = 2, - SGE_CNTXT_OFLD = 4, - SGE_CNTXT_CTRL = 5 -}; - -enum { - AN_PKT_SIZE = 32, /* async notification packet size */ - IMMED_PKT_SIZE = 48 /* packet size for immediate data */ -}; - -struct sg_ent { /* SGE scatter/gather entry */ - u32 len[2]; - u64 addr[2]; -}; - -#ifndef SGE_NUM_GENBITS -/* Must be 1 or 2 */ -# define SGE_NUM_GENBITS 2 -#endif - -#define TX_DESC_FLITS 16U -#define WR_FLITS (TX_DESC_FLITS + 1 - SGE_NUM_GENBITS) - -struct cphy; -struct adapter; - -struct mdio_ops { - int (*read)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*write)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); -}; - -struct adapter_info { - unsigned char nports; /* # of ports */ - unsigned char phy_base_addr; /* MDIO PHY base address */ - unsigned char mdien; - unsigned char mdiinv; - unsigned int gpio_out; /* GPIO output settings */ - unsigned int gpio_intr; /* GPIO IRQ enable mask */ - unsigned long caps; /* adapter capabilities */ - const struct mdio_ops *mdio_ops; /* MDIO operations */ - const char *desc; /* product description */ -}; - -struct port_type_info { - void (*phy_prep)(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *ops); - unsigned int caps; - const char *desc; -}; - -struct mc5_stats { - unsigned long parity_err; - unsigned long active_rgn_full; - unsigned long nfa_srch_err; - unsigned long unknown_cmd; - unsigned long reqq_parity_err; - unsigned long dispq_parity_err; - unsigned long del_act_empty; -}; - -struct mc7_stats { - unsigned long corr_err; - unsigned long uncorr_err; - unsigned long parity_err; - unsigned long addr_err; -}; - -struct mac_stats { - u64 tx_octets; /* total # of octets in good frames */ - u64 tx_octets_bad; /* total # of octets in error frames */ - u64 tx_frames; /* all good frames */ - u64 tx_mcast_frames; /* good multicast frames */ - u64 tx_bcast_frames; /* good broadcast frames */ - u64 tx_pause; /* # of transmitted pause frames */ - u64 tx_deferred; /* frames with deferred transmissions */ - u64 tx_late_collisions; /* # of late collisions */ - u64 tx_total_collisions; /* # of total collisions */ - u64 tx_excess_collisions; /* frame errors from excessive collissions */ - u64 tx_underrun; /* # of Tx FIFO underruns */ - u64 tx_len_errs; /* # of Tx length errors */ - u64 tx_mac_internal_errs; /* # of internal MAC errors on Tx */ - u64 tx_excess_deferral; /* # of frames with excessive deferral */ - u64 tx_fcs_errs; /* # of frames with bad FCS */ - - u64 tx_frames_64; /* # of Tx frames in a particular range */ - u64 tx_frames_65_127; - u64 tx_frames_128_255; - u64 tx_frames_256_511; - u64 tx_frames_512_1023; - u64 tx_frames_1024_1518; - u64 tx_frames_1519_max; - - u64 rx_octets; /* total # of octets in good frames */ - u64 rx_octets_bad; /* total # of octets in error frames */ - u64 rx_frames; /* all good frames */ - u64 rx_mcast_frames; /* good multicast frames */ - u64 rx_bcast_frames; /* good broadcast frames */ - u64 rx_pause; /* # of received pause frames */ - u64 rx_fcs_errs; /* # of received frames with bad FCS */ - u64 rx_align_errs; /* alignment errors */ - u64 rx_symbol_errs; /* symbol errors */ - u64 rx_data_errs; /* data errors */ - u64 rx_sequence_errs; /* sequence errors */ - u64 rx_runt; /* # of runt frames */ - u64 rx_jabber; /* # of jabber frames */ - u64 rx_short; /* # of short frames */ - u64 rx_too_long; /* # of oversized frames */ - u64 rx_mac_internal_errs; /* # of internal MAC errors on Rx */ - - u64 rx_frames_64; /* # of Rx frames in a particular range */ - u64 rx_frames_65_127; - u64 rx_frames_128_255; - u64 rx_frames_256_511; - u64 rx_frames_512_1023; - u64 rx_frames_1024_1518; - u64 rx_frames_1519_max; - - u64 rx_cong_drops; /* # of Rx drops due to SGE congestion */ - - unsigned long tx_fifo_parity_err; - unsigned long rx_fifo_parity_err; - unsigned long tx_fifo_urun; - unsigned long rx_fifo_ovfl; - unsigned long serdes_signal_loss; - unsigned long xaui_pcs_ctc_err; - unsigned long xaui_pcs_align_change; -}; - -struct tp_mib_stats { - u32 ipInReceive_hi; - u32 ipInReceive_lo; - u32 ipInHdrErrors_hi; - u32 ipInHdrErrors_lo; - u32 ipInAddrErrors_hi; - u32 ipInAddrErrors_lo; - u32 ipInUnknownProtos_hi; - u32 ipInUnknownProtos_lo; - u32 ipInDiscards_hi; - u32 ipInDiscards_lo; - u32 ipInDelivers_hi; - u32 ipInDelivers_lo; - u32 ipOutRequests_hi; - u32 ipOutRequests_lo; - u32 ipOutDiscards_hi; - u32 ipOutDiscards_lo; - u32 ipOutNoRoutes_hi; - u32 ipOutNoRoutes_lo; - u32 ipReasmTimeout; - u32 ipReasmReqds; - u32 ipReasmOKs; - u32 ipReasmFails; - - u32 reserved[8]; - - u32 tcpActiveOpens; - u32 tcpPassiveOpens; - u32 tcpAttemptFails; - u32 tcpEstabResets; - u32 tcpOutRsts; - u32 tcpCurrEstab; - u32 tcpInSegs_hi; - u32 tcpInSegs_lo; - u32 tcpOutSegs_hi; - u32 tcpOutSegs_lo; - u32 tcpRetransSeg_hi; - u32 tcpRetransSeg_lo; - u32 tcpInErrs_hi; - u32 tcpInErrs_lo; - u32 tcpRtoMin; - u32 tcpRtoMax; -}; - -struct tp_params { - unsigned int nchan; /* # of channels */ - unsigned int pmrx_size; /* total PMRX capacity */ - unsigned int pmtx_size; /* total PMTX capacity */ - unsigned int cm_size; /* total CM capacity */ - unsigned int chan_rx_size; /* per channel Rx size */ - unsigned int chan_tx_size; /* per channel Tx size */ - unsigned int rx_pg_size; /* Rx page size */ - unsigned int tx_pg_size; /* Tx page size */ - unsigned int rx_num_pgs; /* # of Rx pages */ - unsigned int tx_num_pgs; /* # of Tx pages */ - unsigned int ntimer_qs; /* # of timer queues */ -}; - -struct qset_params { /* SGE queue set parameters */ - unsigned int polling; /* polling/interrupt service for rspq */ - unsigned int coalesce_usecs; /* irq coalescing timer */ - unsigned int rspq_size; /* # of entries in response queue */ - unsigned int fl_size; /* # of entries in regular free list */ - unsigned int jumbo_size; /* # of entries in jumbo free list */ - unsigned int txq_size[SGE_TXQ_PER_SET]; /* Tx queue sizes */ - unsigned int cong_thres; /* FL congestion threshold */ -}; - -struct sge_params { - unsigned int max_pkt_size; /* max offload pkt size */ - struct qset_params qset[SGE_QSETS]; -}; - -struct mc5_params { - unsigned int mode; /* selects MC5 width */ - unsigned int nservers; /* size of server region */ - unsigned int nfilters; /* size of filter region */ - unsigned int nroutes; /* size of routing region */ -}; - -/* Default MC5 region sizes */ -enum { - DEFAULT_NSERVERS = 512, - DEFAULT_NFILTERS = 128 -}; - -/* MC5 modes, these must be non-0 */ -enum { - MC5_MODE_144_BIT = 1, - MC5_MODE_72_BIT = 2 -}; - -struct vpd_params { - unsigned int cclk; - unsigned int mclk; - unsigned int uclk; - unsigned int mdc; - unsigned int mem_timing; - u8 eth_base[6]; - u8 port_type[MAX_NPORTS]; - unsigned short xauicfg[2]; -}; - -struct pci_params { - unsigned int vpd_cap_addr; - unsigned int pcie_cap_addr; - unsigned short speed; - unsigned char width; - unsigned char variant; -}; - -enum { - PCI_VARIANT_PCI, - PCI_VARIANT_PCIX_MODE1_PARITY, - PCI_VARIANT_PCIX_MODE1_ECC, - PCI_VARIANT_PCIX_266_MODE2, - PCI_VARIANT_PCIE -}; - -struct adapter_params { - struct sge_params sge; - struct mc5_params mc5; - struct tp_params tp; - struct vpd_params vpd; - struct pci_params pci; - - const struct adapter_info *info; - - unsigned short mtus[NMTUS]; - unsigned short a_wnd[NCCTRL_WIN]; - unsigned short b_wnd[NCCTRL_WIN]; - - unsigned int nports; /* # of ethernet ports */ - unsigned int stats_update_period; /* MAC stats accumulation period */ - unsigned int linkpoll_period; /* link poll period in 0.1s */ - unsigned int rev; /* chip revision */ -}; - -struct trace_params { - u32 sip; - u32 sip_mask; - u32 dip; - u32 dip_mask; - u16 sport; - u16 sport_mask; - u16 dport; - u16 dport_mask; - u32 vlan:12; - u32 vlan_mask:12; - u32 intf:4; - u32 intf_mask:4; - u8 proto; - u8 proto_mask; -}; - -struct link_config { - unsigned int supported; /* link capabilities */ - unsigned int advertising; /* advertised capabilities */ - unsigned short requested_speed; /* speed user has requested */ - unsigned short speed; /* actual link speed */ - unsigned char requested_duplex; /* duplex user has requested */ - unsigned char duplex; /* actual link duplex */ - unsigned char requested_fc; /* flow control user has requested */ - unsigned char fc; /* actual link flow control */ - unsigned char autoneg; /* autonegotiating? */ - unsigned int link_ok; /* link up? */ -}; - -#define SPEED_INVALID 0xffff -#define DUPLEX_INVALID 0xff - -struct mc5 { - struct adapter *adapter; - unsigned int tcam_size; - unsigned char part_type; - unsigned char parity_enabled; - unsigned char mode; - struct mc5_stats stats; -}; - -static inline unsigned int t3_mc5_size(const struct mc5 *p) -{ - return p->tcam_size; -} - -struct mc7 { - struct adapter *adapter; /* backpointer to adapter */ - unsigned int size; /* memory size in bytes */ - unsigned int width; /* MC7 interface width */ - unsigned int offset; /* register address offset for MC7 instance */ - const char *name; /* name of MC7 instance */ - struct mc7_stats stats; /* MC7 statistics */ -}; - -static inline unsigned int t3_mc7_size(const struct mc7 *p) -{ - return p->size; -} - -struct cmac { - struct adapter *adapter; - unsigned int offset; - unsigned int nucast; /* # of address filters for unicast MACs */ - struct mac_stats stats; -}; - -enum { - MAC_DIRECTION_RX = 1, - MAC_DIRECTION_TX = 2, - MAC_RXFIFO_SIZE = 32768 -}; - -/* IEEE 802.3ae specified MDIO devices */ -enum { - MDIO_DEV_PMA_PMD = 1, - MDIO_DEV_WIS = 2, - MDIO_DEV_PCS = 3, - MDIO_DEV_XGXS = 4 -}; - -/* PHY loopback direction */ -enum { - PHY_LOOPBACK_TX = 1, - PHY_LOOPBACK_RX = 2 -}; - -/* PHY interrupt types */ -enum { - cphy_cause_link_change = 1, - cphy_cause_fifo_error = 2 -}; - -/* PHY operations */ -struct cphy_ops { - void (*destroy)(struct cphy *phy); - int (*reset)(struct cphy *phy, int wait); - - int (*intr_enable)(struct cphy *phy); - int (*intr_disable)(struct cphy *phy); - int (*intr_clear)(struct cphy *phy); - int (*intr_handler)(struct cphy *phy); - - int (*autoneg_enable)(struct cphy *phy); - int (*autoneg_restart)(struct cphy *phy); - - int (*advertise)(struct cphy *phy, unsigned int advertise_map); - int (*set_loopback)(struct cphy *phy, int mmd, int dir, int enable); - int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex); - int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed, - int *duplex, int *fc); - int (*power_down)(struct cphy *phy, int enable); -}; - -/* A PHY instance */ -struct cphy { - int addr; /* PHY address */ - struct adapter *adapter; /* associated adapter */ - unsigned long fifo_errors; /* FIFO over/under-flows */ - const struct cphy_ops *ops; /* PHY operations */ - int (*mdio_read)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *val); - int (*mdio_write)(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val); -}; - -/* Convenience MDIO read/write wrappers */ -static inline int mdio_read(struct cphy *phy, int mmd, int reg, - unsigned int *valp) -{ - return phy->mdio_read(phy->adapter, phy->addr, mmd, reg, valp); -} - -static inline int mdio_write(struct cphy *phy, int mmd, int reg, - unsigned int val) -{ - return phy->mdio_write(phy->adapter, phy->addr, mmd, reg, val); -} - -/* Convenience initializer */ -static inline void cphy_init(struct cphy *phy, struct adapter *adapter, - int phy_addr, struct cphy_ops *phy_ops, - const struct mdio_ops *mdio_ops) -{ - phy->adapter = adapter; - phy->addr = phy_addr; - phy->ops = phy_ops; - if (mdio_ops) { - phy->mdio_read = mdio_ops->read; - phy->mdio_write = mdio_ops->write; - } -} - -/* Accumulate MAC statistics every 180 seconds. For 1G we multiply by 10. */ -#define MAC_STATS_ACCUM_SECS 180 - -#define XGM_REG(reg_addr, idx) \ - ((reg_addr) + (idx) * (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR)) - -struct addr_val_pair { - unsigned int reg_addr; - unsigned int val; -}; - -#include "adapter.h" - -#ifndef PCI_VENDOR_ID_CHELSIO -# define PCI_VENDOR_ID_CHELSIO 0x1425 -#endif - -#define for_each_port(adapter, iter) \ - for (iter = 0; iter < (adapter)->params.nports; ++iter) - -#define adapter_info(adap) ((adap)->params.info) - -static inline int uses_xaui(const struct adapter *adap) -{ - return adapter_info(adap)->caps & SUPPORTED_AUI; -} - -static inline int is_10G(const struct adapter *adap) -{ - return adapter_info(adap)->caps & SUPPORTED_10000baseT_Full; -} - -static inline int is_offload(const struct adapter *adap) -{ - return adapter_info(adap)->caps & SUPPORTED_OFFLOAD; -} - -static inline unsigned int core_ticks_per_usec(const struct adapter *adap) -{ - return adap->params.vpd.cclk / 1000; -} - -static inline unsigned int is_pcie(const struct adapter *adap) -{ - return adap->params.pci.variant == PCI_VARIANT_PCIE; -} - -void t3_set_reg_field(struct adapter *adap, unsigned int addr, u32 mask, - u32 val); -void t3_write_regs(struct adapter *adapter, const struct addr_val_pair *p, - int n, unsigned int offset); -int t3_wait_op_done_val(struct adapter *adapter, int reg, u32 mask, - int polarity, int attempts, int delay, u32 *valp); -static inline int t3_wait_op_done(struct adapter *adapter, int reg, u32 mask, - int polarity, int attempts, int delay) -{ - return t3_wait_op_done_val(adapter, reg, mask, polarity, attempts, - delay, NULL); -} -int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear, - unsigned int set); -int t3_phy_reset(struct cphy *phy, int mmd, int wait); -int t3_phy_advertise(struct cphy *phy, unsigned int advert); -int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex); - -void t3_intr_enable(struct adapter *adapter); -void t3_intr_disable(struct adapter *adapter); -void t3_intr_clear(struct adapter *adapter); -void t3_port_intr_enable(struct adapter *adapter, int idx); -void t3_port_intr_disable(struct adapter *adapter, int idx); -void t3_port_intr_clear(struct adapter *adapter, int idx); -int t3_slow_intr_handler(struct adapter *adapter); -int t3_phy_intr_handler(struct adapter *adapter); - -void t3_link_changed(struct adapter *adapter, int port_id); -int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc); -const struct adapter_info *t3_get_adapter_info(unsigned int board_id); -int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data); -int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data); -int t3_seeprom_wp(struct adapter *adapter, int enable); -int t3_read_flash(struct adapter *adapter, unsigned int addr, - unsigned int nwords, u32 *data, int byte_oriented); -int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size); -int t3_get_fw_version(struct adapter *adapter, u32 *vers); -int t3_check_fw_version(struct adapter *adapter); -int t3_init_hw(struct adapter *adapter, u32 fw_params); -void mac_prep(struct cmac *mac, struct adapter *adapter, int index); -void early_hw_init(struct adapter *adapter, const struct adapter_info *ai); -int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, - int reset); -void t3_led_ready(struct adapter *adapter); -void t3_fatal_err(struct adapter *adapter); -void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on); -void t3_config_rss(struct adapter *adapter, unsigned int rss_config, - const u8 * cpus, const u16 *rspq); -int t3_read_rss(struct adapter *adapter, u8 * lkup, u16 *map); -int t3_mps_set_active_ports(struct adapter *adap, unsigned int port_mask); -int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr, - unsigned int n, unsigned int *valp); -int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n, - u64 *buf); - -int t3_mac_reset(struct cmac *mac); -void t3b_pcs_reset(struct cmac *mac); -int t3_mac_enable(struct cmac *mac, int which); -int t3_mac_disable(struct cmac *mac, int which); -int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu); -int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm); -int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]); -int t3_mac_set_num_ucast(struct cmac *mac, int n); -const struct mac_stats *t3_mac_update_stats(struct cmac *mac); -int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc); - -void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode); -int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, - unsigned int nroutes); -void t3_mc5_intr_handler(struct mc5 *mc5); -int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start, unsigned int n, - u32 *buf); - -int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh); -void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size); -void t3_tp_set_offload_mode(struct adapter *adap, int enable); -void t3_tp_get_mib_stats(struct adapter *adap, struct tp_mib_stats *tps); -void t3_load_mtus(struct adapter *adap, unsigned short mtus[NMTUS], - unsigned short alpha[NCCTRL_WIN], - unsigned short beta[NCCTRL_WIN], unsigned short mtu_cap); -void t3_read_hw_mtus(struct adapter *adap, unsigned short mtus[NMTUS]); -void t3_get_cong_cntl_tab(struct adapter *adap, - unsigned short incr[NMTUS][NCCTRL_WIN]); -void t3_config_trace_filter(struct adapter *adapter, - const struct trace_params *tp, int filter_index, - int invert, int enable); -int t3_config_sched(struct adapter *adap, unsigned int kbps, int sched); - -void t3_sge_prep(struct adapter *adap, struct sge_params *p); -void t3_sge_init(struct adapter *adap, struct sge_params *p); -int t3_sge_init_ecntxt(struct adapter *adapter, unsigned int id, int gts_enable, - enum sge_context_type type, int respq, u64 base_addr, - unsigned int size, unsigned int token, int gen, - unsigned int cidx); -int t3_sge_init_flcntxt(struct adapter *adapter, unsigned int id, - int gts_enable, u64 base_addr, unsigned int size, - unsigned int esize, unsigned int cong_thres, int gen, - unsigned int cidx); -int t3_sge_init_rspcntxt(struct adapter *adapter, unsigned int id, - int irq_vec_idx, u64 base_addr, unsigned int size, - unsigned int fl_thres, int gen, unsigned int cidx); -int t3_sge_init_cqcntxt(struct adapter *adapter, unsigned int id, u64 base_addr, - unsigned int size, int rspq, int ovfl_mode, - unsigned int credits, unsigned int credit_thres); -int t3_sge_enable_ecntxt(struct adapter *adapter, unsigned int id, int enable); -int t3_sge_disable_fl(struct adapter *adapter, unsigned int id); -int t3_sge_disable_rspcntxt(struct adapter *adapter, unsigned int id); -int t3_sge_disable_cqcntxt(struct adapter *adapter, unsigned int id); -int t3_sge_read_ecntxt(struct adapter *adapter, unsigned int id, u32 data[4]); -int t3_sge_read_fl(struct adapter *adapter, unsigned int id, u32 data[4]); -int t3_sge_read_cq(struct adapter *adapter, unsigned int id, u32 data[4]); -int t3_sge_read_rspq(struct adapter *adapter, unsigned int id, u32 data[4]); -int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op, - unsigned int credits); - -void t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *mdio_ops); -void t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *mdio_ops); -void t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *mdio_ops); -void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, - const struct mdio_ops *mdio_ops); -void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *mdio_ops); -#endif /* __CHELSIO_COMMON_H */ diff --git a/trunk/drivers/net/cxgb3/cxgb3_ctl_defs.h b/trunk/drivers/net/cxgb3/cxgb3_ctl_defs.h deleted file mode 100644 index 2095ddacff78..000000000000 --- a/trunk/drivers/net/cxgb3/cxgb3_ctl_defs.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _CXGB3_OFFLOAD_CTL_DEFS_H -#define _CXGB3_OFFLOAD_CTL_DEFS_H - -enum { - GET_MAX_OUTSTANDING_WR, - GET_TX_MAX_CHUNK, - GET_TID_RANGE, - GET_STID_RANGE, - GET_RTBL_RANGE, - GET_L2T_CAPACITY, - GET_MTUS, - GET_WR_LEN, - GET_IFF_FROM_MAC, - GET_DDP_PARAMS, - GET_PORTS, - - ULP_ISCSI_GET_PARAMS, - ULP_ISCSI_SET_PARAMS, - - RDMA_GET_PARAMS, - RDMA_CQ_OP, - RDMA_CQ_SETUP, - RDMA_CQ_DISABLE, - RDMA_CTRL_QP_SETUP, - RDMA_GET_MEM, -}; - -/* - * Structure used to describe a TID range. Valid TIDs are [base, base+num). - */ -struct tid_range { - unsigned int base; /* first TID */ - unsigned int num; /* number of TIDs in range */ -}; - -/* - * Structure used to request the size and contents of the MTU table. - */ -struct mtutab { - unsigned int size; /* # of entries in the MTU table */ - const unsigned short *mtus; /* the MTU table values */ -}; - -struct net_device; - -/* - * Structure used to request the adapter net_device owning a given MAC address. - */ -struct iff_mac { - struct net_device *dev; /* the net_device */ - const unsigned char *mac_addr; /* MAC address to lookup */ - u16 vlan_tag; -}; - -struct pci_dev; - -/* - * Structure used to request the TCP DDP parameters. - */ -struct ddp_params { - unsigned int llimit; /* TDDP region start address */ - unsigned int ulimit; /* TDDP region end address */ - unsigned int tag_mask; /* TDDP tag mask */ - struct pci_dev *pdev; -}; - -struct adap_ports { - unsigned int nports; /* number of ports on this adapter */ - struct net_device *lldevs[2]; -}; - -/* - * Structure used to return information to the iscsi layer. - */ -struct ulp_iscsi_info { - unsigned int offset; - unsigned int llimit; - unsigned int ulimit; - unsigned int tagmask; - unsigned int pgsz3; - unsigned int pgsz2; - unsigned int pgsz1; - unsigned int pgsz0; - unsigned int max_rxsz; - unsigned int max_txsz; - struct pci_dev *pdev; -}; - -/* - * Structure used to return information to the RDMA layer. - */ -struct rdma_info { - unsigned int tpt_base; /* TPT base address */ - unsigned int tpt_top; /* TPT last entry address */ - unsigned int pbl_base; /* PBL base address */ - unsigned int pbl_top; /* PBL last entry address */ - unsigned int rqt_base; /* RQT base address */ - unsigned int rqt_top; /* RQT last entry address */ - unsigned int udbell_len; /* user doorbell region length */ - unsigned long udbell_physbase; /* user doorbell physical start addr */ - void __iomem *kdb_addr; /* kernel doorbell register address */ - struct pci_dev *pdev; /* associated PCI device */ -}; - -/* - * Structure used to request an operation on an RDMA completion queue. - */ -struct rdma_cq_op { - unsigned int id; - unsigned int op; - unsigned int credits; -}; - -/* - * Structure used to setup RDMA completion queues. - */ -struct rdma_cq_setup { - unsigned int id; - unsigned long long base_addr; - unsigned int size; - unsigned int credits; - unsigned int credit_thres; - unsigned int ovfl_mode; -}; - -/* - * Structure used to setup the RDMA control egress context. - */ -struct rdma_ctrlqp_setup { - unsigned long long base_addr; - unsigned int size; -}; -#endif /* _CXGB3_OFFLOAD_CTL_DEFS_H */ diff --git a/trunk/drivers/net/cxgb3/cxgb3_defs.h b/trunk/drivers/net/cxgb3/cxgb3_defs.h deleted file mode 100644 index 16e004990c59..000000000000 --- a/trunk/drivers/net/cxgb3/cxgb3_defs.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved. - * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _CHELSIO_DEFS_H -#define _CHELSIO_DEFS_H - -#include -#include - -#include "t3cdev.h" - -#include "cxgb3_offload.h" - -#define VALIDATE_TID 1 - -void *cxgb_alloc_mem(unsigned long size); -void cxgb_free_mem(void *addr); -void cxgb_neigh_update(struct neighbour *neigh); -void cxgb_redirect(struct dst_entry *old, struct dst_entry *new); - -/* - * Map an ATID or STID to their entries in the corresponding TID tables. - */ -static inline union active_open_entry *atid2entry(const struct tid_info *t, - unsigned int atid) -{ - return &t->atid_tab[atid - t->atid_base]; -} - -static inline union listen_entry *stid2entry(const struct tid_info *t, - unsigned int stid) -{ - return &t->stid_tab[stid - t->stid_base]; -} - -/* - * Find the connection corresponding to a TID. - */ -static inline struct t3c_tid_entry *lookup_tid(const struct tid_info *t, - unsigned int tid) -{ - return tid < t->ntids ? &(t->tid_tab[tid]) : NULL; -} - -/* - * Find the connection corresponding to a server TID. - */ -static inline struct t3c_tid_entry *lookup_stid(const struct tid_info *t, - unsigned int tid) -{ - if (tid < t->stid_base || tid >= t->stid_base + t->nstids) - return NULL; - return &(stid2entry(t, tid)->t3c_tid); -} - -/* - * Find the connection corresponding to an active-open TID. - */ -static inline struct t3c_tid_entry *lookup_atid(const struct tid_info *t, - unsigned int tid) -{ - if (tid < t->atid_base || tid >= t->atid_base + t->natids) - return NULL; - return &(atid2entry(t, tid)->t3c_tid); -} - -int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n); -int attach_t3cdev(struct t3cdev *dev); -void detach_t3cdev(struct t3cdev *dev); -#endif diff --git a/trunk/drivers/net/cxgb3/cxgb3_ioctl.h b/trunk/drivers/net/cxgb3/cxgb3_ioctl.h deleted file mode 100644 index a94281861a66..000000000000 --- a/trunk/drivers/net/cxgb3/cxgb3_ioctl.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef __CHIOCTL_H__ -#define __CHIOCTL_H__ - -/* - * Ioctl commands specific to this driver. - */ -enum { - CHELSIO_SETREG = 1024, - CHELSIO_GETREG, - CHELSIO_SETTPI, - CHELSIO_GETTPI, - CHELSIO_GETMTUTAB, - CHELSIO_SETMTUTAB, - CHELSIO_GETMTU, - CHELSIO_SET_PM, - CHELSIO_GET_PM, - CHELSIO_GET_TCAM, - CHELSIO_SET_TCAM, - CHELSIO_GET_TCB, - CHELSIO_GET_MEM, - CHELSIO_LOAD_FW, - CHELSIO_GET_PROTO, - CHELSIO_SET_PROTO, - CHELSIO_SET_TRACE_FILTER, - CHELSIO_SET_QSET_PARAMS, - CHELSIO_GET_QSET_PARAMS, - CHELSIO_SET_QSET_NUM, - CHELSIO_GET_QSET_NUM, - CHELSIO_SET_PKTSCHED, -}; - -struct ch_reg { - uint32_t cmd; - uint32_t addr; - uint32_t val; -}; - -struct ch_cntxt { - uint32_t cmd; - uint32_t cntxt_type; - uint32_t cntxt_id; - uint32_t data[4]; -}; - -/* context types */ -enum { CNTXT_TYPE_EGRESS, CNTXT_TYPE_FL, CNTXT_TYPE_RSP, CNTXT_TYPE_CQ }; - -struct ch_desc { - uint32_t cmd; - uint32_t queue_num; - uint32_t idx; - uint32_t size; - uint8_t data[128]; -}; - -struct ch_mem_range { - uint32_t cmd; - uint32_t mem_id; - uint32_t addr; - uint32_t len; - uint32_t version; - uint8_t buf[0]; -}; - -struct ch_qset_params { - uint32_t cmd; - uint32_t qset_idx; - int32_t txq_size[3]; - int32_t rspq_size; - int32_t fl_size[2]; - int32_t intr_lat; - int32_t polling; - int32_t cong_thres; -}; - -struct ch_pktsched_params { - uint32_t cmd; - uint8_t sched; - uint8_t idx; - uint8_t min; - uint8_t max; - uint8_t binding; -}; - -#ifndef TCB_SIZE -# define TCB_SIZE 128 -#endif - -/* TCB size in 32-bit words */ -#define TCB_WORDS (TCB_SIZE / 4) - -enum { MEM_CM, MEM_PMRX, MEM_PMTX }; /* ch_mem_range.mem_id values */ - -struct ch_mtus { - uint32_t cmd; - uint32_t nmtus; - uint16_t mtus[NMTUS]; -}; - -struct ch_pm { - uint32_t cmd; - uint32_t tx_pg_sz; - uint32_t tx_num_pg; - uint32_t rx_pg_sz; - uint32_t rx_num_pg; - uint32_t pm_total; -}; - -struct ch_tcam { - uint32_t cmd; - uint32_t tcam_size; - uint32_t nservers; - uint32_t nroutes; - uint32_t nfilters; -}; - -struct ch_tcb { - uint32_t cmd; - uint32_t tcb_index; - uint32_t tcb_data[TCB_WORDS]; -}; - -struct ch_tcam_word { - uint32_t cmd; - uint32_t addr; - uint32_t buf[3]; -}; - -struct ch_trace { - uint32_t cmd; - uint32_t sip; - uint32_t sip_mask; - uint32_t dip; - uint32_t dip_mask; - uint16_t sport; - uint16_t sport_mask; - uint16_t dport; - uint16_t dport_mask; - uint32_t vlan:12; - uint32_t vlan_mask:12; - uint32_t intf:4; - uint32_t intf_mask:4; - uint8_t proto; - uint8_t proto_mask; - uint8_t invert_match:1; - uint8_t config_tx:1; - uint8_t config_rx:1; - uint8_t trace_tx:1; - uint8_t trace_rx:1; -}; - -#define SIOCCHIOCTL SIOCDEVPRIVATE - -#endif diff --git a/trunk/drivers/net/cxgb3/cxgb3_main.c b/trunk/drivers/net/cxgb3/cxgb3_main.c deleted file mode 100644 index dfa035a1ad45..000000000000 --- a/trunk/drivers/net/cxgb3/cxgb3_main.c +++ /dev/null @@ -1,2515 +0,0 @@ -/* - * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "cxgb3_ioctl.h" -#include "regs.h" -#include "cxgb3_offload.h" -#include "version.h" - -#include "cxgb3_ctl_defs.h" -#include "t3_cpl.h" -#include "firmware_exports.h" - -enum { - MAX_TXQ_ENTRIES = 16384, - MAX_CTRL_TXQ_ENTRIES = 1024, - MAX_RSPQ_ENTRIES = 16384, - MAX_RX_BUFFERS = 16384, - MAX_RX_JUMBO_BUFFERS = 16384, - MIN_TXQ_ENTRIES = 4, - MIN_CTRL_TXQ_ENTRIES = 4, - MIN_RSPQ_ENTRIES = 32, - MIN_FL_ENTRIES = 32 -}; - -#define PORT_MASK ((1 << MAX_NPORTS) - 1) - -#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \ - NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ - NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) - -#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 } - -static const struct pci_device_id cxgb3_pci_tbl[] = { - CH_DEVICE(0x20, 1, 0), /* PE9000 */ - CH_DEVICE(0x21, 1, 1), /* T302E */ - CH_DEVICE(0x22, 1, 2), /* T310E */ - CH_DEVICE(0x23, 1, 3), /* T320X */ - CH_DEVICE(0x24, 1, 1), /* T302X */ - CH_DEVICE(0x25, 1, 3), /* T320E */ - CH_DEVICE(0x26, 1, 2), /* T310X */ - CH_DEVICE(0x30, 1, 2), /* T3B10 */ - CH_DEVICE(0x31, 1, 3), /* T3B20 */ - CH_DEVICE(0x32, 1, 1), /* T3B02 */ - {0,} -}; - -MODULE_DESCRIPTION(DRV_DESC); -MODULE_AUTHOR("Chelsio Communications"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_DEVICE_TABLE(pci, cxgb3_pci_tbl); - -static int dflt_msg_enable = DFLT_MSG_ENABLE; - -module_param(dflt_msg_enable, int, 0644); -MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T3 default message enable bitmap"); - -/* - * The driver uses the best interrupt scheme available on a platform in the - * order MSI-X, MSI, legacy pin interrupts. This parameter determines which - * of these schemes the driver may consider as follows: - * - * msi = 2: choose from among all three options - * msi = 1: only consider MSI and pin interrupts - * msi = 0: force pin interrupts - */ -static int msi = 2; - -module_param(msi, int, 0644); -MODULE_PARM_DESC(msi, "whether to use MSI or MSI-X"); - -/* - * The driver enables offload as a default. - * To disable it, use ofld_disable = 1. - */ - -static int ofld_disable = 0; - -module_param(ofld_disable, int, 0644); -MODULE_PARM_DESC(ofld_disable, "whether to enable offload at init time or not"); - -/* - * We have work elements that we need to cancel when an interface is taken - * down. Normally the work elements would be executed by keventd but that - * can deadlock because of linkwatch. If our close method takes the rtnl - * lock and linkwatch is ahead of our work elements in keventd, linkwatch - * will block keventd as it needs the rtnl lock, and we'll deadlock waiting - * for our work to complete. Get our own work queue to solve this. - */ -static struct workqueue_struct *cxgb3_wq; - -/** - * link_report - show link status and link speed/duplex - * @p: the port whose settings are to be reported - * - * Shows the link status, speed, and duplex of a port. - */ -static void link_report(struct net_device *dev) -{ - if (!netif_carrier_ok(dev)) - printk(KERN_INFO "%s: link down\n", dev->name); - else { - const char *s = "10Mbps"; - const struct port_info *p = netdev_priv(dev); - - switch (p->link_config.speed) { - case SPEED_10000: - s = "10Gbps"; - break; - case SPEED_1000: - s = "1000Mbps"; - break; - case SPEED_100: - s = "100Mbps"; - break; - } - - printk(KERN_INFO "%s: link up, %s, %s-duplex\n", dev->name, s, - p->link_config.duplex == DUPLEX_FULL ? "full" : "half"); - } -} - -/** - * t3_os_link_changed - handle link status changes - * @adapter: the adapter associated with the link change - * @port_id: the port index whose limk status has changed - * @link_stat: the new status of the link - * @speed: the new speed setting - * @duplex: the new duplex setting - * @pause: the new flow-control setting - * - * This is the OS-dependent handler for link status changes. The OS - * neutral handler takes care of most of the processing for these events, - * then calls this handler for any OS-specific processing. - */ -void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, - int speed, int duplex, int pause) -{ - struct net_device *dev = adapter->port[port_id]; - - /* Skip changes from disabled ports. */ - if (!netif_running(dev)) - return; - - if (link_stat != netif_carrier_ok(dev)) { - if (link_stat) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - link_report(dev); - } -} - -static void cxgb_set_rxmode(struct net_device *dev) -{ - struct t3_rx_mode rm; - struct port_info *pi = netdev_priv(dev); - - init_rx_mode(&rm, dev, dev->mc_list); - t3_mac_set_rx_mode(&pi->mac, &rm); -} - -/** - * link_start - enable a port - * @dev: the device to enable - * - * Performs the MAC and PHY actions needed to enable a port. - */ -static void link_start(struct net_device *dev) -{ - struct t3_rx_mode rm; - struct port_info *pi = netdev_priv(dev); - struct cmac *mac = &pi->mac; - - init_rx_mode(&rm, dev, dev->mc_list); - t3_mac_reset(mac); - t3_mac_set_mtu(mac, dev->mtu); - t3_mac_set_address(mac, 0, dev->dev_addr); - t3_mac_set_rx_mode(mac, &rm); - t3_link_start(&pi->phy, mac, &pi->link_config); - t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX); -} - -static inline void cxgb_disable_msi(struct adapter *adapter) -{ - if (adapter->flags & USING_MSIX) { - pci_disable_msix(adapter->pdev); - adapter->flags &= ~USING_MSIX; - } else if (adapter->flags & USING_MSI) { - pci_disable_msi(adapter->pdev); - adapter->flags &= ~USING_MSI; - } -} - -/* - * Interrupt handler for asynchronous events used with MSI-X. - */ -static irqreturn_t t3_async_intr_handler(int irq, void *cookie) -{ - t3_slow_intr_handler(cookie); - return IRQ_HANDLED; -} - -/* - * Name the MSI-X interrupts. - */ -static void name_msix_vecs(struct adapter *adap) -{ - int i, j, msi_idx = 1, n = sizeof(adap->msix_info[0].desc) - 1; - - snprintf(adap->msix_info[0].desc, n, "%s", adap->name); - adap->msix_info[0].desc[n] = 0; - - for_each_port(adap, j) { - struct net_device *d = adap->port[j]; - const struct port_info *pi = netdev_priv(d); - - for (i = 0; i < pi->nqsets; i++, msi_idx++) { - snprintf(adap->msix_info[msi_idx].desc, n, - "%s (queue %d)", d->name, i); - adap->msix_info[msi_idx].desc[n] = 0; - } - } -} - -static int request_msix_data_irqs(struct adapter *adap) -{ - int i, j, err, qidx = 0; - - for_each_port(adap, i) { - int nqsets = adap2pinfo(adap, i)->nqsets; - - for (j = 0; j < nqsets; ++j) { - err = request_irq(adap->msix_info[qidx + 1].vec, - t3_intr_handler(adap, - adap->sge.qs[qidx]. - rspq.polling), 0, - adap->msix_info[qidx + 1].desc, - &adap->sge.qs[qidx]); - if (err) { - while (--qidx >= 0) - free_irq(adap->msix_info[qidx + 1].vec, - &adap->sge.qs[qidx]); - return err; - } - qidx++; - } - } - return 0; -} - -/** - * setup_rss - configure RSS - * @adap: the adapter - * - * Sets up RSS to distribute packets to multiple receive queues. We - * configure the RSS CPU lookup table to distribute to the number of HW - * receive queues, and the response queue lookup table to narrow that - * down to the response queues actually configured for each port. - * We always configure the RSS mapping for two ports since the mapping - * table has plenty of entries. - */ -static void setup_rss(struct adapter *adap) -{ - int i; - unsigned int nq0 = adap2pinfo(adap, 0)->nqsets; - unsigned int nq1 = adap->port[1] ? adap2pinfo(adap, 1)->nqsets : 1; - u8 cpus[SGE_QSETS + 1]; - u16 rspq_map[RSS_TABLE_SIZE]; - - for (i = 0; i < SGE_QSETS; ++i) - cpus[i] = i; - cpus[SGE_QSETS] = 0xff; /* terminator */ - - for (i = 0; i < RSS_TABLE_SIZE / 2; ++i) { - rspq_map[i] = i % nq0; - rspq_map[i + RSS_TABLE_SIZE / 2] = (i % nq1) + nq0; - } - - t3_config_rss(adap, F_RQFEEDBACKENABLE | F_TNLLKPEN | F_TNLMAPEN | - F_TNLPRTEN | F_TNL2TUPEN | F_TNL4TUPEN | - V_RRCPLCPUSIZE(6), cpus, rspq_map); -} - -/* - * If we have multiple receive queues per port serviced by NAPI we need one - * netdevice per queue as NAPI operates on netdevices. We already have one - * netdevice, namely the one associated with the interface, so we use dummy - * ones for any additional queues. Note that these netdevices exist purely - * so that NAPI has something to work with, they do not represent network - * ports and are not registered. - */ -static int init_dummy_netdevs(struct adapter *adap) -{ - int i, j, dummy_idx = 0; - struct net_device *nd; - - for_each_port(adap, i) { - struct net_device *dev = adap->port[i]; - const struct port_info *pi = netdev_priv(dev); - - for (j = 0; j < pi->nqsets - 1; j++) { - if (!adap->dummy_netdev[dummy_idx]) { - nd = alloc_netdev(0, "", ether_setup); - if (!nd) - goto free_all; - - nd->priv = adap; - nd->weight = 64; - set_bit(__LINK_STATE_START, &nd->state); - adap->dummy_netdev[dummy_idx] = nd; - } - strcpy(adap->dummy_netdev[dummy_idx]->name, dev->name); - dummy_idx++; - } - } - return 0; - -free_all: - while (--dummy_idx >= 0) { - free_netdev(adap->dummy_netdev[dummy_idx]); - adap->dummy_netdev[dummy_idx] = NULL; - } - return -ENOMEM; -} - -/* - * Wait until all NAPI handlers are descheduled. This includes the handlers of - * both netdevices representing interfaces and the dummy ones for the extra - * queues. - */ -static void quiesce_rx(struct adapter *adap) -{ - int i; - struct net_device *dev; - - for_each_port(adap, i) { - dev = adap->port[i]; - while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) - msleep(1); - } - - for (i = 0; i < ARRAY_SIZE(adap->dummy_netdev); i++) { - dev = adap->dummy_netdev[i]; - if (dev) - while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) - msleep(1); - } -} - -/** - * setup_sge_qsets - configure SGE Tx/Rx/response queues - * @adap: the adapter - * - * Determines how many sets of SGE queues to use and initializes them. - * We support multiple queue sets per port if we have MSI-X, otherwise - * just one queue set per port. - */ -static int setup_sge_qsets(struct adapter *adap) -{ - int i, j, err, irq_idx = 0, qset_idx = 0, dummy_dev_idx = 0; - unsigned int ntxq = is_offload(adap) ? SGE_TXQ_PER_SET : 1; - - if (adap->params.rev > 0 && !(adap->flags & USING_MSI)) - irq_idx = -1; - - for_each_port(adap, i) { - struct net_device *dev = adap->port[i]; - const struct port_info *pi = netdev_priv(dev); - - for (j = 0; j < pi->nqsets; ++j, ++qset_idx) { - err = t3_sge_alloc_qset(adap, qset_idx, 1, - (adap->flags & USING_MSIX) ? qset_idx + 1 : - irq_idx, - &adap->params.sge.qset[qset_idx], ntxq, - j == 0 ? dev : - adap-> dummy_netdev[dummy_dev_idx++]); - if (err) { - t3_free_sge_resources(adap); - return err; - } - } - } - - return 0; -} - -static ssize_t attr_show(struct class_device *cd, char *buf, - ssize_t(*format) (struct adapter *, char *)) -{ - ssize_t len; - struct adapter *adap = to_net_dev(cd)->priv; - - /* Synchronize with ioctls that may shut down the device */ - rtnl_lock(); - len = (*format) (adap, buf); - rtnl_unlock(); - return len; -} - -static ssize_t attr_store(struct class_device *cd, 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; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - val = simple_strtoul(buf, &endp, 0); - if (endp == buf || val < min_val || val > max_val) - return -EINVAL; - - rtnl_lock(); - ret = (*set) (adap, val); - if (!ret) - ret = len; - rtnl_unlock(); - return ret; -} - -#define CXGB3_SHOW(name, val_expr) \ -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) \ -{ \ - return attr_show(cd, buf, format_##name); \ -} - -static ssize_t set_nfilters(struct adapter *adap, unsigned int val) -{ - if (adap->flags & FULL_INIT_DONE) - return -EBUSY; - if (val && adap->params.rev == 0) - return -EINVAL; - if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers) - return -EINVAL; - adap->params.mc5.nfilters = val; - return 0; -} - -static ssize_t store_nfilters(struct class_device *cd, const char *buf, - size_t len) -{ - return attr_store(cd, buf, len, set_nfilters, 0, ~0); -} - -static ssize_t set_nservers(struct adapter *adap, unsigned int val) -{ - if (adap->flags & FULL_INIT_DONE) - return -EBUSY; - if (val > t3_mc5_size(&adap->mc5) - adap->params.mc5.nfilters) - return -EINVAL; - adap->params.mc5.nservers = val; - return 0; -} - -static ssize_t store_nservers(struct class_device *cd, const char *buf, - size_t len) -{ - return attr_store(cd, 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) - -#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) - -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, - 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) -{ - ssize_t len; - unsigned int v, addr, bpt, cpt; - struct adapter *adap = to_net_dev(cd)->priv; - - addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2; - rtnl_lock(); - t3_write_reg(adap, A_TP_TM_PIO_ADDR, addr); - v = t3_read_reg(adap, A_TP_TM_PIO_DATA); - if (sched & 1) - v >>= 16; - bpt = (v >> 8) & 0xff; - cpt = v & 0xff; - if (!cpt) - len = sprintf(buf, "disabled\n"); - else { - v = (adap->params.vpd.cclk * 1000) / cpt; - len = sprintf(buf, "%u Kbps\n", (v * bpt) / 125); - } - rtnl_unlock(); - return len; -} - -static ssize_t tm_attr_store(struct class_device *cd, const char *buf, - size_t len, int sched) -{ - char *endp; - ssize_t ret; - unsigned int val; - struct adapter *adap = to_net_dev(cd)->priv; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - val = simple_strtoul(buf, &endp, 0); - if (endp == buf || val > 10000000) - return -EINVAL; - - rtnl_lock(); - ret = t3_config_sched(adap, val, sched); - if (!ret) - ret = len; - rtnl_unlock(); - return ret; -} - -#define TM_ATTR(name, sched) \ -static ssize_t show_##name(struct class_device *cd, char *buf) \ -{ \ - return tm_attr_show(cd, buf, sched); \ -} \ -static ssize_t store_##name(struct class_device *cd, const char *buf, size_t len) \ -{ \ - return tm_attr_store(cd, buf, len, sched); \ -} \ -static CLASS_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name) - -TM_ATTR(sched0, 0); -TM_ATTR(sched1, 1); -TM_ATTR(sched2, 2); -TM_ATTR(sched3, 3); -TM_ATTR(sched4, 4); -TM_ATTR(sched5, 5); -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, - NULL -}; - -static struct attribute_group offload_attr_group = {.attrs = offload_attrs }; - -/* - * Sends an sk_buff to an offload queue driver - * after dealing with any active network taps. - */ -static inline int offload_tx(struct t3cdev *tdev, struct sk_buff *skb) -{ - int ret; - - local_bh_disable(); - ret = t3_offload_tx(tdev, skb); - local_bh_enable(); - return ret; -} - -static int write_smt_entry(struct adapter *adapter, int idx) -{ - struct cpl_smt_write_req *req; - struct sk_buff *skb = alloc_skb(sizeof(*req), GFP_KERNEL); - - if (!skb) - return -ENOMEM; - - req = (struct cpl_smt_write_req *)__skb_put(skb, sizeof(*req)); - req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); - OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, idx)); - req->mtu_idx = NMTUS - 1; /* should be 0 but there's a T3 bug */ - req->iff = idx; - memset(req->src_mac1, 0, sizeof(req->src_mac1)); - memcpy(req->src_mac0, adapter->port[idx]->dev_addr, ETH_ALEN); - skb->priority = 1; - offload_tx(&adapter->tdev, skb); - return 0; -} - -static int init_smt(struct adapter *adapter) -{ - int i; - - for_each_port(adapter, i) - write_smt_entry(adapter, i); - return 0; -} - -static void init_port_mtus(struct adapter *adapter) -{ - unsigned int mtus = adapter->port[0]->mtu; - - if (adapter->port[1]) - mtus |= adapter->port[1]->mtu << 16; - t3_write_reg(adapter, A_TP_MTU_PORT_TABLE, mtus); -} - -static void send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo, - int hi, int port) -{ - struct sk_buff *skb; - struct mngt_pktsched_wr *req; - - skb = alloc_skb(sizeof(*req), GFP_KERNEL | __GFP_NOFAIL); - req = (struct mngt_pktsched_wr *)skb_put(skb, sizeof(*req)); - req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT)); - req->mngt_opcode = FW_MNGTOPCODE_PKTSCHED_SET; - req->sched = sched; - req->idx = qidx; - req->min = lo; - req->max = hi; - req->binding = port; - t3_mgmt_tx(adap, skb); -} - -static void bind_qsets(struct adapter *adap) -{ - int i, j; - - for_each_port(adap, i) { - const struct port_info *pi = adap2pinfo(adap, i); - - for (j = 0; j < pi->nqsets; ++j) - send_pktsched_cmd(adap, 1, pi->first_qset + j, -1, - -1, i); - } -} - -/** - * cxgb_up - enable the adapter - * @adapter: adapter being enabled - * - * Called when the first port is enabled, this function performs the - * actions necessary to make an adapter operational, such as completing - * the initialization of HW modules, and enabling interrupts. - * - * Must be called with the rtnl lock held. - */ -static int cxgb_up(struct adapter *adap) -{ - int err = 0; - - if (!(adap->flags & FULL_INIT_DONE)) { - err = t3_check_fw_version(adap); - if (err) - goto out; - - err = init_dummy_netdevs(adap); - if (err) - goto out; - - err = t3_init_hw(adap, 0); - if (err) - goto out; - - err = setup_sge_qsets(adap); - if (err) - goto out; - - setup_rss(adap); - adap->flags |= FULL_INIT_DONE; - } - - t3_intr_clear(adap); - - if (adap->flags & USING_MSIX) { - name_msix_vecs(adap); - err = request_irq(adap->msix_info[0].vec, - t3_async_intr_handler, 0, - adap->msix_info[0].desc, adap); - if (err) - goto irq_err; - - if (request_msix_data_irqs(adap)) { - free_irq(adap->msix_info[0].vec, adap); - goto irq_err; - } - } else if ((err = request_irq(adap->pdev->irq, - t3_intr_handler(adap, - adap->sge.qs[0].rspq. - polling), - (adap->flags & USING_MSI) ? 0 : SA_SHIRQ, - adap->name, adap))) - goto irq_err; - - t3_sge_start(adap); - t3_intr_enable(adap); - - if ((adap->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX) - bind_qsets(adap); - adap->flags |= QUEUES_BOUND; - -out: - return err; -irq_err: - CH_ERR(adap, "request_irq failed, err %d\n", err); - goto out; -} - -/* - * Release resources when all the ports and offloading have been stopped. - */ -static void cxgb_down(struct adapter *adapter) -{ - t3_sge_stop(adapter); - spin_lock_irq(&adapter->work_lock); /* sync with PHY intr task */ - t3_intr_disable(adapter); - spin_unlock_irq(&adapter->work_lock); - - if (adapter->flags & USING_MSIX) { - int i, n = 0; - - free_irq(adapter->msix_info[0].vec, adapter); - for_each_port(adapter, i) - n += adap2pinfo(adapter, i)->nqsets; - - for (i = 0; i < n; ++i) - free_irq(adapter->msix_info[i + 1].vec, - &adapter->sge.qs[i]); - } else - free_irq(adapter->pdev->irq, adapter); - - flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */ - quiesce_rx(adapter); -} - -static void schedule_chk_task(struct adapter *adap) -{ - unsigned int timeo; - - timeo = adap->params.linkpoll_period ? - (HZ * adap->params.linkpoll_period) / 10 : - adap->params.stats_update_period * HZ; - if (timeo) - queue_delayed_work(cxgb3_wq, &adap->adap_check_task, timeo); -} - -static int offload_open(struct net_device *dev) -{ - struct adapter *adapter = dev->priv; - struct t3cdev *tdev = T3CDEV(dev); - int adap_up = adapter->open_device_map & PORT_MASK; - int err = 0; - - if (test_and_set_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) - return 0; - - if (!adap_up && (err = cxgb_up(adapter)) < 0) - return err; - - t3_tp_set_offload_mode(adapter, 1); - tdev->lldev = adapter->port[0]; - err = cxgb3_offload_activate(adapter); - if (err) - goto out; - - init_port_mtus(adapter); - t3_load_mtus(adapter, adapter->params.mtus, adapter->params.a_wnd, - adapter->params.b_wnd, - adapter->params.rev == 0 ? - adapter->port[0]->mtu : 0xffff); - init_smt(adapter); - - /* Never mind if the next step fails */ - sysfs_create_group(&tdev->lldev->class_dev.kobj, &offload_attr_group); - - /* Call back all registered clients */ - cxgb3_add_clients(tdev); - -out: - /* restore them in case the offload module has changed them */ - if (err) { - t3_tp_set_offload_mode(adapter, 0); - clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map); - cxgb3_set_dummy_ops(tdev); - } - return err; -} - -static int offload_close(struct t3cdev *tdev) -{ - struct adapter *adapter = tdev2adap(tdev); - - if (!test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) - return 0; - - /* Call back all registered clients */ - cxgb3_remove_clients(tdev); - - sysfs_remove_group(&tdev->lldev->class_dev.kobj, &offload_attr_group); - - tdev->lldev = NULL; - cxgb3_set_dummy_ops(tdev); - t3_tp_set_offload_mode(adapter, 0); - clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map); - - if (!adapter->open_device_map) - cxgb_down(adapter); - - cxgb3_offload_deactivate(adapter); - return 0; -} - -static int cxgb_open(struct net_device *dev) -{ - int err; - struct adapter *adapter = dev->priv; - struct port_info *pi = netdev_priv(dev); - int other_ports = adapter->open_device_map & PORT_MASK; - - if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) - return err; - - set_bit(pi->port_id, &adapter->open_device_map); - if (!ofld_disable) { - err = offload_open(dev); - if (err) - printk(KERN_WARNING - "Could not initialize offload capabilities\n"); - } - - link_start(dev); - t3_port_intr_enable(adapter, pi->port_id); - netif_start_queue(dev); - if (!other_ports) - schedule_chk_task(adapter); - - return 0; -} - -static int cxgb_close(struct net_device *dev) -{ - struct adapter *adapter = dev->priv; - struct port_info *p = netdev_priv(dev); - - t3_port_intr_disable(adapter, p->port_id); - netif_stop_queue(dev); - p->phy.ops->power_down(&p->phy, 1); - netif_carrier_off(dev); - t3_mac_disable(&p->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX); - - spin_lock(&adapter->work_lock); /* sync with update task */ - clear_bit(p->port_id, &adapter->open_device_map); - spin_unlock(&adapter->work_lock); - - if (!(adapter->open_device_map & PORT_MASK)) - cancel_rearming_delayed_workqueue(cxgb3_wq, - &adapter->adap_check_task); - - if (!adapter->open_device_map) - cxgb_down(adapter); - - return 0; -} - -static struct net_device_stats *cxgb_get_stats(struct net_device *dev) -{ - struct adapter *adapter = dev->priv; - struct port_info *p = netdev_priv(dev); - struct net_device_stats *ns = &p->netstats; - const struct mac_stats *pstats; - - spin_lock(&adapter->stats_lock); - pstats = t3_mac_update_stats(&p->mac); - spin_unlock(&adapter->stats_lock); - - ns->tx_bytes = pstats->tx_octets; - ns->tx_packets = pstats->tx_frames; - ns->rx_bytes = pstats->rx_octets; - ns->rx_packets = pstats->rx_frames; - ns->multicast = pstats->rx_mcast_frames; - - ns->tx_errors = pstats->tx_underrun; - ns->rx_errors = pstats->rx_symbol_errs + pstats->rx_fcs_errs + - pstats->rx_too_long + pstats->rx_jabber + pstats->rx_short + - pstats->rx_fifo_ovfl; - - /* detailed rx_errors */ - ns->rx_length_errors = pstats->rx_jabber + pstats->rx_too_long; - ns->rx_over_errors = 0; - ns->rx_crc_errors = pstats->rx_fcs_errs; - ns->rx_frame_errors = pstats->rx_symbol_errs; - ns->rx_fifo_errors = pstats->rx_fifo_ovfl; - ns->rx_missed_errors = pstats->rx_cong_drops; - - /* detailed tx_errors */ - ns->tx_aborted_errors = 0; - ns->tx_carrier_errors = 0; - ns->tx_fifo_errors = pstats->tx_underrun; - ns->tx_heartbeat_errors = 0; - ns->tx_window_errors = 0; - return ns; -} - -static u32 get_msglevel(struct net_device *dev) -{ - struct adapter *adapter = dev->priv; - - return adapter->msg_enable; -} - -static void set_msglevel(struct net_device *dev, u32 val) -{ - struct adapter *adapter = dev->priv; - - adapter->msg_enable = val; -} - -static char stats_strings[][ETH_GSTRING_LEN] = { - "TxOctetsOK ", - "TxFramesOK ", - "TxMulticastFramesOK", - "TxBroadcastFramesOK", - "TxPauseFrames ", - "TxUnderrun ", - "TxExtUnderrun ", - - "TxFrames64 ", - "TxFrames65To127 ", - "TxFrames128To255 ", - "TxFrames256To511 ", - "TxFrames512To1023 ", - "TxFrames1024To1518 ", - "TxFrames1519ToMax ", - - "RxOctetsOK ", - "RxFramesOK ", - "RxMulticastFramesOK", - "RxBroadcastFramesOK", - "RxPauseFrames ", - "RxFCSErrors ", - "RxSymbolErrors ", - "RxShortErrors ", - "RxJabberErrors ", - "RxLengthErrors ", - "RxFIFOoverflow ", - - "RxFrames64 ", - "RxFrames65To127 ", - "RxFrames128To255 ", - "RxFrames256To511 ", - "RxFrames512To1023 ", - "RxFrames1024To1518 ", - "RxFrames1519ToMax ", - - "PhyFIFOErrors ", - "TSO ", - "VLANextractions ", - "VLANinsertions ", - "TxCsumOffload ", - "RxCsumGood ", - "RxDrops " -}; - -static int get_stats_count(struct net_device *dev) -{ - return ARRAY_SIZE(stats_strings); -} - -#define T3_REGMAP_SIZE (3 * 1024) - -static int get_regs_len(struct net_device *dev) -{ - return T3_REGMAP_SIZE; -} - -static int get_eeprom_len(struct net_device *dev) -{ - return EEPROMSIZE; -} - -static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - u32 fw_vers = 0; - struct adapter *adapter = dev->priv; - - t3_get_fw_version(adapter, &fw_vers); - - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - strcpy(info->bus_info, pci_name(adapter->pdev)); - if (!fw_vers) - strcpy(info->fw_version, "N/A"); - else { - snprintf(info->fw_version, sizeof(info->fw_version), - "%s %u.%u.%u", - G_FW_VERSION_TYPE(fw_vers) ? "T" : "N", - G_FW_VERSION_MAJOR(fw_vers), - G_FW_VERSION_MINOR(fw_vers), - G_FW_VERSION_MICRO(fw_vers)); - } -} - -static void get_strings(struct net_device *dev, u32 stringset, u8 * data) -{ - if (stringset == ETH_SS_STATS) - memcpy(data, stats_strings, sizeof(stats_strings)); -} - -static unsigned long collect_sge_port_stats(struct adapter *adapter, - struct port_info *p, int idx) -{ - int i; - unsigned long tot = 0; - - for (i = 0; i < p->nqsets; ++i) - tot += adapter->sge.qs[i + p->first_qset].port_stats[idx]; - return tot; -} - -static void get_stats(struct net_device *dev, struct ethtool_stats *stats, - u64 *data) -{ - struct adapter *adapter = dev->priv; - struct port_info *pi = netdev_priv(dev); - const struct mac_stats *s; - - spin_lock(&adapter->stats_lock); - s = t3_mac_update_stats(&pi->mac); - spin_unlock(&adapter->stats_lock); - - *data++ = s->tx_octets; - *data++ = s->tx_frames; - *data++ = s->tx_mcast_frames; - *data++ = s->tx_bcast_frames; - *data++ = s->tx_pause; - *data++ = s->tx_underrun; - *data++ = s->tx_fifo_urun; - - *data++ = s->tx_frames_64; - *data++ = s->tx_frames_65_127; - *data++ = s->tx_frames_128_255; - *data++ = s->tx_frames_256_511; - *data++ = s->tx_frames_512_1023; - *data++ = s->tx_frames_1024_1518; - *data++ = s->tx_frames_1519_max; - - *data++ = s->rx_octets; - *data++ = s->rx_frames; - *data++ = s->rx_mcast_frames; - *data++ = s->rx_bcast_frames; - *data++ = s->rx_pause; - *data++ = s->rx_fcs_errs; - *data++ = s->rx_symbol_errs; - *data++ = s->rx_short; - *data++ = s->rx_jabber; - *data++ = s->rx_too_long; - *data++ = s->rx_fifo_ovfl; - - *data++ = s->rx_frames_64; - *data++ = s->rx_frames_65_127; - *data++ = s->rx_frames_128_255; - *data++ = s->rx_frames_256_511; - *data++ = s->rx_frames_512_1023; - *data++ = s->rx_frames_1024_1518; - *data++ = s->rx_frames_1519_max; - - *data++ = pi->phy.fifo_errors; - - *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TSO); - *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANEX); - *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANINS); - *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); - *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); - *data++ = s->rx_cong_drops; -} - -static inline void reg_block_dump(struct adapter *ap, void *buf, - unsigned int start, unsigned int end) -{ - u32 *p = buf + start; - - for (; start <= end; start += sizeof(u32)) - *p++ = t3_read_reg(ap, start); -} - -static void get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *buf) -{ - struct adapter *ap = dev->priv; - - /* - * Version scheme: - * bits 0..9: chip version - * bits 10..15: chip revision - * bit 31: set for PCIe cards - */ - regs->version = 3 | (ap->params.rev << 10) | (is_pcie(ap) << 31); - - /* - * We skip the MAC statistics registers because they are clear-on-read. - * Also reading multi-register stats would need to synchronize with the - * periodic mac stats accumulation. Hard to justify the complexity. - */ - memset(buf, 0, T3_REGMAP_SIZE); - reg_block_dump(ap, buf, 0, A_SG_RSPQ_CREDIT_RETURN); - reg_block_dump(ap, buf, A_SG_HI_DRB_HI_THRSH, A_ULPRX_PBL_ULIMIT); - reg_block_dump(ap, buf, A_ULPTX_CONFIG, A_MPS_INT_CAUSE); - reg_block_dump(ap, buf, A_CPL_SWITCH_CNTRL, A_CPL_MAP_TBL_DATA); - reg_block_dump(ap, buf, A_SMB_GLOBAL_TIME_CFG, A_XGM_SERDES_STAT3); - reg_block_dump(ap, buf, A_XGM_SERDES_STATUS0, - XGM_REG(A_XGM_SERDES_STAT3, 1)); - reg_block_dump(ap, buf, XGM_REG(A_XGM_SERDES_STATUS0, 1), - XGM_REG(A_XGM_RX_SPI4_SOP_EOP_CNT, 1)); -} - -static int restart_autoneg(struct net_device *dev) -{ - struct port_info *p = netdev_priv(dev); - - if (!netif_running(dev)) - return -EAGAIN; - if (p->link_config.autoneg != AUTONEG_ENABLE) - return -EINVAL; - p->phy.ops->autoneg_restart(&p->phy); - return 0; -} - -static int cxgb3_phys_id(struct net_device *dev, u32 data) -{ - int i; - struct adapter *adapter = dev->priv; - - if (data == 0) - data = 2; - - for (i = 0; i < data * 2; i++) { - t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, - (i & 1) ? F_GPIO0_OUT_VAL : 0); - if (msleep_interruptible(500)) - break; - } - t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, - F_GPIO0_OUT_VAL); - return 0; -} - -static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct port_info *p = netdev_priv(dev); - - cmd->supported = p->link_config.supported; - cmd->advertising = p->link_config.advertising; - - if (netif_carrier_ok(dev)) { - cmd->speed = p->link_config.speed; - cmd->duplex = p->link_config.duplex; - } else { - cmd->speed = -1; - cmd->duplex = -1; - } - - cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; - cmd->phy_address = p->phy.addr; - cmd->transceiver = XCVR_EXTERNAL; - cmd->autoneg = p->link_config.autoneg; - cmd->maxtxpkt = 0; - cmd->maxrxpkt = 0; - return 0; -} - -static int speed_duplex_to_caps(int speed, int duplex) -{ - int cap = 0; - - switch (speed) { - case SPEED_10: - if (duplex == DUPLEX_FULL) - cap = SUPPORTED_10baseT_Full; - else - cap = SUPPORTED_10baseT_Half; - break; - case SPEED_100: - if (duplex == DUPLEX_FULL) - cap = SUPPORTED_100baseT_Full; - else - cap = SUPPORTED_100baseT_Half; - break; - case SPEED_1000: - if (duplex == DUPLEX_FULL) - cap = SUPPORTED_1000baseT_Full; - else - cap = SUPPORTED_1000baseT_Half; - break; - case SPEED_10000: - if (duplex == DUPLEX_FULL) - cap = SUPPORTED_10000baseT_Full; - } - return cap; -} - -#define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \ - ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \ - ADVERTISED_10000baseT_Full) - -static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct port_info *p = netdev_priv(dev); - struct link_config *lc = &p->link_config; - - if (!(lc->supported & SUPPORTED_Autoneg)) - return -EOPNOTSUPP; /* can't change speed/duplex */ - - if (cmd->autoneg == AUTONEG_DISABLE) { - int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex); - - if (!(lc->supported & cap) || cmd->speed == SPEED_1000) - return -EINVAL; - lc->requested_speed = cmd->speed; - lc->requested_duplex = cmd->duplex; - lc->advertising = 0; - } else { - cmd->advertising &= ADVERTISED_MASK; - cmd->advertising &= lc->supported; - if (!cmd->advertising) - return -EINVAL; - lc->requested_speed = SPEED_INVALID; - lc->requested_duplex = DUPLEX_INVALID; - lc->advertising = cmd->advertising | ADVERTISED_Autoneg; - } - lc->autoneg = cmd->autoneg; - if (netif_running(dev)) - t3_link_start(&p->phy, &p->mac, lc); - return 0; -} - -static void get_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *epause) -{ - struct port_info *p = netdev_priv(dev); - - epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0; - epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0; - epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0; -} - -static int set_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *epause) -{ - struct port_info *p = netdev_priv(dev); - struct link_config *lc = &p->link_config; - - if (epause->autoneg == AUTONEG_DISABLE) - lc->requested_fc = 0; - else if (lc->supported & SUPPORTED_Autoneg) - lc->requested_fc = PAUSE_AUTONEG; - else - return -EINVAL; - - if (epause->rx_pause) - lc->requested_fc |= PAUSE_RX; - if (epause->tx_pause) - lc->requested_fc |= PAUSE_TX; - if (lc->autoneg == AUTONEG_ENABLE) { - if (netif_running(dev)) - t3_link_start(&p->phy, &p->mac, lc); - } else { - lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); - if (netif_running(dev)) - t3_mac_set_speed_duplex_fc(&p->mac, -1, -1, lc->fc); - } - return 0; -} - -static u32 get_rx_csum(struct net_device *dev) -{ - struct port_info *p = netdev_priv(dev); - - return p->rx_csum_offload; -} - -static int set_rx_csum(struct net_device *dev, u32 data) -{ - struct port_info *p = netdev_priv(dev); - - p->rx_csum_offload = data; - return 0; -} - -static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) -{ - struct adapter *adapter = dev->priv; - - e->rx_max_pending = MAX_RX_BUFFERS; - e->rx_mini_max_pending = 0; - e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS; - e->tx_max_pending = MAX_TXQ_ENTRIES; - - e->rx_pending = adapter->params.sge.qset[0].fl_size; - e->rx_mini_pending = adapter->params.sge.qset[0].rspq_size; - e->rx_jumbo_pending = adapter->params.sge.qset[0].jumbo_size; - e->tx_pending = adapter->params.sge.qset[0].txq_size[0]; -} - -static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) -{ - int i; - struct adapter *adapter = dev->priv; - - if (e->rx_pending > MAX_RX_BUFFERS || - e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS || - e->tx_pending > MAX_TXQ_ENTRIES || - e->rx_mini_pending > MAX_RSPQ_ENTRIES || - e->rx_mini_pending < MIN_RSPQ_ENTRIES || - e->rx_pending < MIN_FL_ENTRIES || - e->rx_jumbo_pending < MIN_FL_ENTRIES || - e->tx_pending < adapter->params.nports * MIN_TXQ_ENTRIES) - return -EINVAL; - - if (adapter->flags & FULL_INIT_DONE) - return -EBUSY; - - for (i = 0; i < SGE_QSETS; ++i) { - struct qset_params *q = &adapter->params.sge.qset[i]; - - q->rspq_size = e->rx_mini_pending; - q->fl_size = e->rx_pending; - q->jumbo_size = e->rx_jumbo_pending; - q->txq_size[0] = e->tx_pending; - q->txq_size[1] = e->tx_pending; - q->txq_size[2] = e->tx_pending; - } - return 0; -} - -static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) -{ - struct adapter *adapter = dev->priv; - struct qset_params *qsp = &adapter->params.sge.qset[0]; - struct sge_qset *qs = &adapter->sge.qs[0]; - - if (c->rx_coalesce_usecs * 10 > M_NEWTIMER) - return -EINVAL; - - qsp->coalesce_usecs = c->rx_coalesce_usecs; - t3_update_qset_coalesce(qs, qsp); - return 0; -} - -static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) -{ - struct adapter *adapter = dev->priv; - struct qset_params *q = adapter->params.sge.qset; - - c->rx_coalesce_usecs = q->coalesce_usecs; - return 0; -} - -static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e, - u8 * data) -{ - int i, err = 0; - struct adapter *adapter = dev->priv; - - u8 *buf = kmalloc(EEPROMSIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - e->magic = EEPROM_MAGIC; - for (i = e->offset & ~3; !err && i < e->offset + e->len; i += 4) - err = t3_seeprom_read(adapter, i, (u32 *) & buf[i]); - - if (!err) - memcpy(data, buf + e->offset, e->len); - kfree(buf); - return err; -} - -static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, - u8 * data) -{ - u8 *buf; - int err = 0; - u32 aligned_offset, aligned_len, *p; - struct adapter *adapter = dev->priv; - - if (eeprom->magic != EEPROM_MAGIC) - return -EINVAL; - - aligned_offset = eeprom->offset & ~3; - aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3; - - if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) { - buf = kmalloc(aligned_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - err = t3_seeprom_read(adapter, aligned_offset, (u32 *) buf); - if (!err && aligned_len > 4) - err = t3_seeprom_read(adapter, - aligned_offset + aligned_len - 4, - (u32 *) & buf[aligned_len - 4]); - if (err) - goto out; - memcpy(buf + (eeprom->offset & 3), data, eeprom->len); - } else - buf = data; - - err = t3_seeprom_wp(adapter, 0); - if (err) - goto out; - - for (p = (u32 *) buf; !err && aligned_len; aligned_len -= 4, p++) { - err = t3_seeprom_write(adapter, aligned_offset, *p); - aligned_offset += 4; - } - - if (!err) - err = t3_seeprom_wp(adapter, 1); -out: - if (buf != data) - kfree(buf); - return err; -} - -static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - wol->supported = 0; - wol->wolopts = 0; - memset(&wol->sopass, 0, sizeof(wol->sopass)); -} - -static const struct ethtool_ops cxgb_ethtool_ops = { - .get_settings = get_settings, - .set_settings = set_settings, - .get_drvinfo = get_drvinfo, - .get_msglevel = get_msglevel, - .set_msglevel = set_msglevel, - .get_ringparam = get_sge_param, - .set_ringparam = set_sge_param, - .get_coalesce = get_coalesce, - .set_coalesce = set_coalesce, - .get_eeprom_len = get_eeprom_len, - .get_eeprom = get_eeprom, - .set_eeprom = set_eeprom, - .get_pauseparam = get_pauseparam, - .set_pauseparam = set_pauseparam, - .get_rx_csum = get_rx_csum, - .set_rx_csum = set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_link = ethtool_op_get_link, - .get_strings = get_strings, - .phys_id = cxgb3_phys_id, - .nway_reset = restart_autoneg, - .get_stats_count = get_stats_count, - .get_ethtool_stats = get_stats, - .get_regs_len = get_regs_len, - .get_regs = get_regs, - .get_wol = get_wol, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, - .get_perm_addr = ethtool_op_get_perm_addr -}; - -static int in_range(int val, int lo, int hi) -{ - return val < 0 || (val <= hi && val >= lo); -} - -static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) -{ - int ret; - u32 cmd; - struct adapter *adapter = dev->priv; - - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - - switch (cmd) { - case CHELSIO_SETREG:{ - struct ch_reg edata; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - if ((edata.addr & 3) != 0 - || edata.addr >= adapter->mmio_len) - return -EINVAL; - writel(edata.val, adapter->regs + edata.addr); - break; - } - case CHELSIO_GETREG:{ - struct ch_reg edata; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - if ((edata.addr & 3) != 0 - || edata.addr >= adapter->mmio_len) - return -EINVAL; - edata.val = readl(adapter->regs + edata.addr); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - break; - } - case CHELSIO_SET_QSET_PARAMS:{ - int i; - struct qset_params *q; - struct ch_qset_params t; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (copy_from_user(&t, useraddr, sizeof(t))) - return -EFAULT; - if (t.qset_idx >= SGE_QSETS) - return -EINVAL; - if (!in_range(t.intr_lat, 0, M_NEWTIMER) || - !in_range(t.cong_thres, 0, 255) || - !in_range(t.txq_size[0], MIN_TXQ_ENTRIES, - MAX_TXQ_ENTRIES) || - !in_range(t.txq_size[1], MIN_TXQ_ENTRIES, - MAX_TXQ_ENTRIES) || - !in_range(t.txq_size[2], MIN_CTRL_TXQ_ENTRIES, - MAX_CTRL_TXQ_ENTRIES) || - !in_range(t.fl_size[0], MIN_FL_ENTRIES, - MAX_RX_BUFFERS) - || !in_range(t.fl_size[1], MIN_FL_ENTRIES, - MAX_RX_JUMBO_BUFFERS) - || !in_range(t.rspq_size, MIN_RSPQ_ENTRIES, - MAX_RSPQ_ENTRIES)) - return -EINVAL; - if ((adapter->flags & FULL_INIT_DONE) && - (t.rspq_size >= 0 || t.fl_size[0] >= 0 || - t.fl_size[1] >= 0 || t.txq_size[0] >= 0 || - t.txq_size[1] >= 0 || t.txq_size[2] >= 0 || - t.polling >= 0 || t.cong_thres >= 0)) - return -EBUSY; - - q = &adapter->params.sge.qset[t.qset_idx]; - - if (t.rspq_size >= 0) - q->rspq_size = t.rspq_size; - if (t.fl_size[0] >= 0) - q->fl_size = t.fl_size[0]; - if (t.fl_size[1] >= 0) - q->jumbo_size = t.fl_size[1]; - if (t.txq_size[0] >= 0) - q->txq_size[0] = t.txq_size[0]; - if (t.txq_size[1] >= 0) - q->txq_size[1] = t.txq_size[1]; - if (t.txq_size[2] >= 0) - q->txq_size[2] = t.txq_size[2]; - if (t.cong_thres >= 0) - q->cong_thres = t.cong_thres; - if (t.intr_lat >= 0) { - struct sge_qset *qs = - &adapter->sge.qs[t.qset_idx]; - - q->coalesce_usecs = t.intr_lat; - t3_update_qset_coalesce(qs, q); - } - if (t.polling >= 0) { - if (adapter->flags & USING_MSIX) - q->polling = t.polling; - else { - /* No polling with INTx for T3A */ - if (adapter->params.rev == 0 && - !(adapter->flags & USING_MSI)) - t.polling = 0; - - for (i = 0; i < SGE_QSETS; i++) { - q = &adapter->params.sge. - qset[i]; - q->polling = t.polling; - } - } - } - break; - } - case CHELSIO_GET_QSET_PARAMS:{ - struct qset_params *q; - struct ch_qset_params t; - - if (copy_from_user(&t, useraddr, sizeof(t))) - return -EFAULT; - if (t.qset_idx >= SGE_QSETS) - return -EINVAL; - - q = &adapter->params.sge.qset[t.qset_idx]; - t.rspq_size = q->rspq_size; - t.txq_size[0] = q->txq_size[0]; - t.txq_size[1] = q->txq_size[1]; - t.txq_size[2] = q->txq_size[2]; - t.fl_size[0] = q->fl_size; - t.fl_size[1] = q->jumbo_size; - t.polling = q->polling; - t.intr_lat = q->coalesce_usecs; - t.cong_thres = q->cong_thres; - - if (copy_to_user(useraddr, &t, sizeof(t))) - return -EFAULT; - break; - } - case CHELSIO_SET_QSET_NUM:{ - struct ch_reg edata; - struct port_info *pi = netdev_priv(dev); - unsigned int i, first_qset = 0, other_qsets = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (adapter->flags & FULL_INIT_DONE) - return -EBUSY; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - if (edata.val < 1 || - (edata.val > 1 && !(adapter->flags & USING_MSIX))) - return -EINVAL; - - for_each_port(adapter, i) - if (adapter->port[i] && adapter->port[i] != dev) - other_qsets += adap2pinfo(adapter, i)->nqsets; - - if (edata.val + other_qsets > SGE_QSETS) - return -EINVAL; - - pi->nqsets = edata.val; - - for_each_port(adapter, i) - if (adapter->port[i]) { - pi = adap2pinfo(adapter, i); - pi->first_qset = first_qset; - first_qset += pi->nqsets; - } - break; - } - case CHELSIO_GET_QSET_NUM:{ - struct ch_reg edata; - struct port_info *pi = netdev_priv(dev); - - edata.cmd = CHELSIO_GET_QSET_NUM; - edata.val = pi->nqsets; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - break; - } - case CHELSIO_LOAD_FW:{ - u8 *fw_data; - struct ch_mem_range t; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (copy_from_user(&t, useraddr, sizeof(t))) - return -EFAULT; - - fw_data = kmalloc(t.len, GFP_KERNEL); - if (!fw_data) - return -ENOMEM; - - if (copy_from_user - (fw_data, useraddr + sizeof(t), t.len)) { - kfree(fw_data); - return -EFAULT; - } - - ret = t3_load_fw(adapter, fw_data, t.len); - kfree(fw_data); - if (ret) - return ret; - break; - } - case CHELSIO_SETMTUTAB:{ - struct ch_mtus m; - int i; - - if (!is_offload(adapter)) - return -EOPNOTSUPP; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (offload_running(adapter)) - return -EBUSY; - if (copy_from_user(&m, useraddr, sizeof(m))) - return -EFAULT; - if (m.nmtus != NMTUS) - return -EINVAL; - if (m.mtus[0] < 81) /* accommodate SACK */ - return -EINVAL; - - /* MTUs must be in ascending order */ - for (i = 1; i < NMTUS; ++i) - if (m.mtus[i] < m.mtus[i - 1]) - return -EINVAL; - - memcpy(adapter->params.mtus, m.mtus, - sizeof(adapter->params.mtus)); - break; - } - case CHELSIO_GET_PM:{ - struct tp_params *p = &adapter->params.tp; - struct ch_pm m = {.cmd = CHELSIO_GET_PM }; - - if (!is_offload(adapter)) - return -EOPNOTSUPP; - m.tx_pg_sz = p->tx_pg_size; - m.tx_num_pg = p->tx_num_pgs; - m.rx_pg_sz = p->rx_pg_size; - m.rx_num_pg = p->rx_num_pgs; - m.pm_total = p->pmtx_size + p->chan_rx_size * p->nchan; - if (copy_to_user(useraddr, &m, sizeof(m))) - return -EFAULT; - break; - } - case CHELSIO_SET_PM:{ - struct ch_pm m; - struct tp_params *p = &adapter->params.tp; - - if (!is_offload(adapter)) - return -EOPNOTSUPP; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (adapter->flags & FULL_INIT_DONE) - return -EBUSY; - if (copy_from_user(&m, useraddr, sizeof(m))) - return -EFAULT; - if (!m.rx_pg_sz || (m.rx_pg_sz & (m.rx_pg_sz - 1)) || - !m.tx_pg_sz || (m.tx_pg_sz & (m.tx_pg_sz - 1))) - return -EINVAL; /* not power of 2 */ - if (!(m.rx_pg_sz & 0x14000)) - return -EINVAL; /* not 16KB or 64KB */ - if (!(m.tx_pg_sz & 0x1554000)) - return -EINVAL; - if (m.tx_num_pg == -1) - m.tx_num_pg = p->tx_num_pgs; - if (m.rx_num_pg == -1) - m.rx_num_pg = p->rx_num_pgs; - if (m.tx_num_pg % 24 || m.rx_num_pg % 24) - return -EINVAL; - if (m.rx_num_pg * m.rx_pg_sz > p->chan_rx_size || - m.tx_num_pg * m.tx_pg_sz > p->chan_tx_size) - return -EINVAL; - p->rx_pg_size = m.rx_pg_sz; - p->tx_pg_size = m.tx_pg_sz; - p->rx_num_pgs = m.rx_num_pg; - p->tx_num_pgs = m.tx_num_pg; - break; - } - case CHELSIO_GET_MEM:{ - struct ch_mem_range t; - struct mc7 *mem; - u64 buf[32]; - - if (!is_offload(adapter)) - return -EOPNOTSUPP; - if (!(adapter->flags & FULL_INIT_DONE)) - return -EIO; /* need the memory controllers */ - if (copy_from_user(&t, useraddr, sizeof(t))) - return -EFAULT; - if ((t.addr & 7) || (t.len & 7)) - return -EINVAL; - if (t.mem_id == MEM_CM) - mem = &adapter->cm; - else if (t.mem_id == MEM_PMRX) - mem = &adapter->pmrx; - else if (t.mem_id == MEM_PMTX) - mem = &adapter->pmtx; - else - return -EINVAL; - - /* - * Version scheme: - * bits 0..9: chip version - * bits 10..15: chip revision - */ - t.version = 3 | (adapter->params.rev << 10); - if (copy_to_user(useraddr, &t, sizeof(t))) - return -EFAULT; - - /* - * Read 256 bytes at a time as len can be large and we don't - * want to use huge intermediate buffers. - */ - useraddr += sizeof(t); /* advance to start of buffer */ - while (t.len) { - unsigned int chunk = - min_t(unsigned int, t.len, sizeof(buf)); - - ret = - t3_mc7_bd_read(mem, t.addr / 8, chunk / 8, - buf); - if (ret) - return ret; - if (copy_to_user(useraddr, buf, chunk)) - return -EFAULT; - useraddr += chunk; - t.addr += chunk; - t.len -= chunk; - } - break; - } - case CHELSIO_SET_TRACE_FILTER:{ - struct ch_trace t; - const struct trace_params *tp; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!offload_running(adapter)) - return -EAGAIN; - if (copy_from_user(&t, useraddr, sizeof(t))) - return -EFAULT; - - tp = (const struct trace_params *)&t.sip; - if (t.config_tx) - t3_config_trace_filter(adapter, tp, 0, - t.invert_match, - t.trace_tx); - if (t.config_rx) - t3_config_trace_filter(adapter, tp, 1, - t.invert_match, - t.trace_rx); - break; - } - case CHELSIO_SET_PKTSCHED:{ - struct ch_pktsched_params p; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!adapter->open_device_map) - return -EAGAIN; /* uP and SGE must be running */ - if (copy_from_user(&p, useraddr, sizeof(p))) - return -EFAULT; - send_pktsched_cmd(adapter, p.sched, p.idx, p.min, p.max, - p.binding); - break; - - } - default: - return -EOPNOTSUPP; - } - return 0; -} - -static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd) -{ - int ret, mmd; - struct adapter *adapter = dev->priv; - struct port_info *pi = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(req); - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = pi->phy.addr; - /* FALLTHRU */ - case SIOCGMIIREG:{ - u32 val; - struct cphy *phy = &pi->phy; - - if (!phy->mdio_read) - return -EOPNOTSUPP; - if (is_10G(adapter)) { - mmd = data->phy_id >> 8; - if (!mmd) - mmd = MDIO_DEV_PCS; - else if (mmd > MDIO_DEV_XGXS) - return -EINVAL; - - ret = - phy->mdio_read(adapter, data->phy_id & 0x1f, - mmd, data->reg_num, &val); - } else - ret = - phy->mdio_read(adapter, data->phy_id & 0x1f, - 0, data->reg_num & 0x1f, - &val); - if (!ret) - data->val_out = val; - break; - } - case SIOCSMIIREG:{ - struct cphy *phy = &pi->phy; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (!phy->mdio_write) - return -EOPNOTSUPP; - if (is_10G(adapter)) { - mmd = data->phy_id >> 8; - if (!mmd) - mmd = MDIO_DEV_PCS; - else if (mmd > MDIO_DEV_XGXS) - return -EINVAL; - - ret = - phy->mdio_write(adapter, - data->phy_id & 0x1f, mmd, - data->reg_num, - data->val_in); - } else - ret = - phy->mdio_write(adapter, - data->phy_id & 0x1f, 0, - data->reg_num & 0x1f, - data->val_in); - break; - } - case SIOCCHIOCTL: - return cxgb_extension_ioctl(dev, req->ifr_data); - default: - return -EOPNOTSUPP; - } - return ret; -} - -static int cxgb_change_mtu(struct net_device *dev, int new_mtu) -{ - int ret; - struct adapter *adapter = dev->priv; - struct port_info *pi = netdev_priv(dev); - - if (new_mtu < 81) /* accommodate SACK */ - return -EINVAL; - if ((ret = t3_mac_set_mtu(&pi->mac, new_mtu))) - return ret; - dev->mtu = new_mtu; - init_port_mtus(adapter); - if (adapter->params.rev == 0 && offload_running(adapter)) - t3_load_mtus(adapter, adapter->params.mtus, - adapter->params.a_wnd, adapter->params.b_wnd, - adapter->port[0]->mtu); - return 0; -} - -static int cxgb_set_mac_addr(struct net_device *dev, void *p) -{ - struct adapter *adapter = dev->priv; - struct port_info *pi = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - t3_mac_set_address(&pi->mac, 0, dev->dev_addr); - if (offload_running(adapter)) - write_smt_entry(adapter, pi->port_id); - return 0; -} - -/** - * t3_synchronize_rx - wait for current Rx processing on a port to complete - * @adap: the adapter - * @p: the port - * - * Ensures that current Rx processing on any of the queues associated with - * the given port completes before returning. We do this by acquiring and - * releasing the locks of the response queues associated with the port. - */ -static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p) -{ - int i; - - for (i = 0; i < p->nqsets; i++) { - struct sge_rspq *q = &adap->sge.qs[i + p->first_qset].rspq; - - spin_lock_irq(&q->lock); - spin_unlock_irq(&q->lock); - } -} - -static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -{ - struct adapter *adapter = dev->priv; - struct port_info *pi = netdev_priv(dev); - - pi->vlan_grp = grp; - if (adapter->params.rev > 0) - t3_set_vlan_accel(adapter, 1 << pi->port_id, grp != NULL); - else { - /* single control for all ports */ - unsigned int i, have_vlans = 0; - for_each_port(adapter, i) - have_vlans |= adap2pinfo(adapter, i)->vlan_grp != NULL; - - t3_set_vlan_accel(adapter, 1, have_vlans); - } - t3_synchronize_rx(adapter, pi); -} - -static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -{ - /* nothing */ -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void cxgb_netpoll(struct net_device *dev) -{ - struct adapter *adapter = dev->priv; - struct sge_qset *qs = dev2qset(dev); - - t3_intr_handler(adapter, qs->rspq.polling) (adapter->pdev->irq, - adapter); -} -#endif - -/* - * Periodic accumulation of MAC statistics. - */ -static void mac_stats_update(struct adapter *adapter) -{ - int i; - - for_each_port(adapter, i) { - struct net_device *dev = adapter->port[i]; - struct port_info *p = netdev_priv(dev); - - if (netif_running(dev)) { - spin_lock(&adapter->stats_lock); - t3_mac_update_stats(&p->mac); - spin_unlock(&adapter->stats_lock); - } - } -} - -static void check_link_status(struct adapter *adapter) -{ - int i; - - for_each_port(adapter, i) { - struct net_device *dev = adapter->port[i]; - struct port_info *p = netdev_priv(dev); - - if (!(p->port_type->caps & SUPPORTED_IRQ) && netif_running(dev)) - t3_link_changed(adapter, i); - } -} - -static void t3_adap_check_task(struct work_struct *work) -{ - struct adapter *adapter = container_of(work, struct adapter, - adap_check_task.work); - const struct adapter_params *p = &adapter->params; - - adapter->check_task_cnt++; - - /* Check link status for PHYs without interrupts */ - if (p->linkpoll_period) - check_link_status(adapter); - - /* Accumulate MAC stats if needed */ - if (!p->linkpoll_period || - (adapter->check_task_cnt * p->linkpoll_period) / 10 >= - p->stats_update_period) { - mac_stats_update(adapter); - adapter->check_task_cnt = 0; - } - - /* Schedule the next check update if any port is active. */ - spin_lock(&adapter->work_lock); - if (adapter->open_device_map & PORT_MASK) - schedule_chk_task(adapter); - spin_unlock(&adapter->work_lock); -} - -/* - * Processes external (PHY) interrupts in process context. - */ -static void ext_intr_task(struct work_struct *work) -{ - struct adapter *adapter = container_of(work, struct adapter, - ext_intr_handler_task); - - t3_phy_intr_handler(adapter); - - /* Now reenable external interrupts */ - spin_lock_irq(&adapter->work_lock); - if (adapter->slow_intr_mask) { - adapter->slow_intr_mask |= F_T3DBG; - t3_write_reg(adapter, A_PL_INT_CAUSE0, F_T3DBG); - t3_write_reg(adapter, A_PL_INT_ENABLE0, - adapter->slow_intr_mask); - } - spin_unlock_irq(&adapter->work_lock); -} - -/* - * Interrupt-context handler for external (PHY) interrupts. - */ -void t3_os_ext_intr_handler(struct adapter *adapter) -{ - /* - * Schedule a task to handle external interrupts as they may be slow - * and we use a mutex to protect MDIO registers. We disable PHY - * interrupts in the meantime and let the task reenable them when - * it's done. - */ - spin_lock(&adapter->work_lock); - if (adapter->slow_intr_mask) { - adapter->slow_intr_mask &= ~F_T3DBG; - t3_write_reg(adapter, A_PL_INT_ENABLE0, - adapter->slow_intr_mask); - queue_work(cxgb3_wq, &adapter->ext_intr_handler_task); - } - spin_unlock(&adapter->work_lock); -} - -void t3_fatal_err(struct adapter *adapter) -{ - unsigned int fw_status[4]; - - if (adapter->flags & FULL_INIT_DONE) { - t3_sge_stop(adapter); - t3_intr_disable(adapter); - } - CH_ALERT(adapter, "encountered fatal error, operation suspended\n"); - if (!t3_cim_ctl_blk_read(adapter, 0xa0, 4, fw_status)) - CH_ALERT(adapter, "FW status: 0x%x, 0x%x, 0x%x, 0x%x\n", - fw_status[0], fw_status[1], - fw_status[2], fw_status[3]); - -} - -static int __devinit cxgb_enable_msix(struct adapter *adap) -{ - struct msix_entry entries[SGE_QSETS + 1]; - int i, err; - - for (i = 0; i < ARRAY_SIZE(entries); ++i) - entries[i].entry = i; - - err = pci_enable_msix(adap->pdev, entries, ARRAY_SIZE(entries)); - if (!err) { - for (i = 0; i < ARRAY_SIZE(entries); ++i) - adap->msix_info[i].vec = entries[i].vector; - } else if (err > 0) - dev_info(&adap->pdev->dev, - "only %d MSI-X vectors left, not using MSI-X\n", err); - return err; -} - -static void __devinit print_port_info(struct adapter *adap, - const struct adapter_info *ai) -{ - static const char *pci_variant[] = { - "PCI", "PCI-X", "PCI-X ECC", "PCI-X 266", "PCI Express" - }; - - int i; - char buf[80]; - - if (is_pcie(adap)) - snprintf(buf, sizeof(buf), "%s x%d", - pci_variant[adap->params.pci.variant], - adap->params.pci.width); - else - snprintf(buf, sizeof(buf), "%s %dMHz/%d-bit", - pci_variant[adap->params.pci.variant], - adap->params.pci.speed, adap->params.pci.width); - - for_each_port(adap, i) { - struct net_device *dev = adap->port[i]; - const struct port_info *pi = netdev_priv(dev); - - if (!test_bit(i, &adap->registered_device_map)) - continue; - printk(KERN_INFO "%s: %s %s RNIC (rev %d) %s%s\n", - dev->name, ai->desc, pi->port_type->desc, - adap->params.rev, buf, - (adap->flags & USING_MSIX) ? " MSI-X" : - (adap->flags & USING_MSI) ? " MSI" : ""); - if (adap->name == dev->name && adap->params.vpd.mclk) - printk(KERN_INFO "%s: %uMB CM, %uMB PMTX, %uMB PMRX\n", - adap->name, t3_mc7_size(&adap->cm) >> 20, - t3_mc7_size(&adap->pmtx) >> 20, - t3_mc7_size(&adap->pmrx) >> 20); - } -} - -static int __devinit init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - static int version_printed; - - int i, err, pci_using_dac = 0; - unsigned long mmio_start, mmio_len; - const struct adapter_info *ai; - struct adapter *adapter = NULL; - struct port_info *pi; - - if (!version_printed) { - printk(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION); - ++version_printed; - } - - if (!cxgb3_wq) { - cxgb3_wq = create_singlethread_workqueue(DRV_NAME); - if (!cxgb3_wq) { - printk(KERN_ERR DRV_NAME - ": cannot initialize work queue\n"); - return -ENOMEM; - } - } - - err = pci_request_regions(pdev, DRV_NAME); - if (err) { - /* Just info, some other driver may have claimed the device. */ - dev_info(&pdev->dev, "cannot obtain PCI resources\n"); - return err; - } - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - goto out_release_regions; - } - - if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { - pci_using_dac = 1; - err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (err) { - dev_err(&pdev->dev, "unable to obtain 64-bit DMA for " - "coherent allocations\n"); - goto out_disable_device; - } - } else if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) != 0) { - dev_err(&pdev->dev, "no usable DMA configuration\n"); - goto out_disable_device; - } - - pci_set_master(pdev); - - mmio_start = pci_resource_start(pdev, 0); - mmio_len = pci_resource_len(pdev, 0); - ai = t3_get_adapter_info(ent->driver_data); - - adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); - if (!adapter) { - err = -ENOMEM; - goto out_disable_device; - } - - adapter->regs = ioremap_nocache(mmio_start, mmio_len); - if (!adapter->regs) { - dev_err(&pdev->dev, "cannot map device registers\n"); - err = -ENOMEM; - goto out_free_adapter; - } - - adapter->pdev = pdev; - adapter->name = pci_name(pdev); - adapter->msg_enable = dflt_msg_enable; - adapter->mmio_len = mmio_len; - - mutex_init(&adapter->mdio_lock); - spin_lock_init(&adapter->work_lock); - spin_lock_init(&adapter->stats_lock); - - INIT_LIST_HEAD(&adapter->adapter_list); - INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task); - INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task); - - for (i = 0; i < ai->nports; ++i) { - struct net_device *netdev; - - netdev = alloc_etherdev(sizeof(struct port_info)); - if (!netdev) { - err = -ENOMEM; - goto out_free_dev; - } - - SET_MODULE_OWNER(netdev); - SET_NETDEV_DEV(netdev, &pdev->dev); - - adapter->port[i] = netdev; - pi = netdev_priv(netdev); - pi->rx_csum_offload = 1; - pi->nqsets = 1; - pi->first_qset = i; - pi->activity = 0; - pi->port_id = i; - netif_carrier_off(netdev); - netdev->irq = pdev->irq; - netdev->mem_start = mmio_start; - netdev->mem_end = mmio_start + mmio_len - 1; - netdev->priv = adapter; - netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; - netdev->features |= NETIF_F_LLTX; - if (pci_using_dac) - netdev->features |= NETIF_F_HIGHDMA; - - netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - netdev->vlan_rx_register = vlan_rx_register; - netdev->vlan_rx_kill_vid = vlan_rx_kill_vid; - - netdev->open = cxgb_open; - netdev->stop = cxgb_close; - netdev->hard_start_xmit = t3_eth_xmit; - netdev->get_stats = cxgb_get_stats; - netdev->set_multicast_list = cxgb_set_rxmode; - netdev->do_ioctl = cxgb_ioctl; - netdev->change_mtu = cxgb_change_mtu; - netdev->set_mac_address = cxgb_set_mac_addr; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = cxgb_netpoll; -#endif - netdev->weight = 64; - - SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops); - } - - pci_set_drvdata(pdev, adapter->port[0]); - if (t3_prep_adapter(adapter, ai, 1) < 0) { - err = -ENODEV; - goto out_free_dev; - } - - /* - * The card is now ready to go. If any errors occur during device - * registration we do not fail the whole card but rather proceed only - * with the ports we manage to register successfully. However we must - * register at least one net device. - */ - for_each_port(adapter, i) { - err = register_netdev(adapter->port[i]); - if (err) - dev_warn(&pdev->dev, - "cannot register net device %s, skipping\n", - adapter->port[i]->name); - else { - /* - * Change the name we use for messages to the name of - * the first successfully registered interface. - */ - if (!adapter->registered_device_map) - adapter->name = adapter->port[i]->name; - - __set_bit(i, &adapter->registered_device_map); - } - } - if (!adapter->registered_device_map) { - dev_err(&pdev->dev, "could not register any net devices\n"); - goto out_free_dev; - } - - /* Driver's ready. Reflect it on LEDs */ - t3_led_ready(adapter); - - if (is_offload(adapter)) { - __set_bit(OFFLOAD_DEVMAP_BIT, &adapter->registered_device_map); - cxgb3_adapter_ofld(adapter); - } - - /* See what interrupts we'll be using */ - if (msi > 1 && cxgb_enable_msix(adapter) == 0) - adapter->flags |= USING_MSIX; - else if (msi > 0 && pci_enable_msi(pdev) == 0) - adapter->flags |= USING_MSI; - - err = sysfs_create_group(&adapter->port[0]->class_dev.kobj, - &cxgb3_attr_group); - - print_port_info(adapter, ai); - return 0; - -out_free_dev: - iounmap(adapter->regs); - for (i = ai->nports - 1; i >= 0; --i) - if (adapter->port[i]) - free_netdev(adapter->port[i]); - -out_free_adapter: - kfree(adapter); - -out_disable_device: - pci_disable_device(pdev); -out_release_regions: - pci_release_regions(pdev); - pci_set_drvdata(pdev, NULL); - return err; -} - -static void __devexit remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev) { - int i; - struct adapter *adapter = dev->priv; - - t3_sge_stop(adapter); - sysfs_remove_group(&adapter->port[0]->class_dev.kobj, - &cxgb3_attr_group); - - for_each_port(adapter, i) - if (test_bit(i, &adapter->registered_device_map)) - unregister_netdev(adapter->port[i]); - - if (is_offload(adapter)) { - cxgb3_adapter_unofld(adapter); - if (test_bit(OFFLOAD_DEVMAP_BIT, - &adapter->open_device_map)) - offload_close(&adapter->tdev); - } - - t3_free_sge_resources(adapter); - cxgb_disable_msi(adapter); - - for (i = 0; i < ARRAY_SIZE(adapter->dummy_netdev); i++) - if (adapter->dummy_netdev[i]) { - free_netdev(adapter->dummy_netdev[i]); - adapter->dummy_netdev[i] = NULL; - } - - for_each_port(adapter, i) - if (adapter->port[i]) - free_netdev(adapter->port[i]); - - iounmap(adapter->regs); - kfree(adapter); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static struct pci_driver driver = { - .name = DRV_NAME, - .id_table = cxgb3_pci_tbl, - .probe = init_one, - .remove = __devexit_p(remove_one), -}; - -static int __init cxgb3_init_module(void) -{ - int ret; - - cxgb3_offload_init(); - - ret = pci_register_driver(&driver); - return ret; -} - -static void __exit cxgb3_cleanup_module(void) -{ - pci_unregister_driver(&driver); - if (cxgb3_wq) - destroy_workqueue(cxgb3_wq); -} - -module_init(cxgb3_init_module); -module_exit(cxgb3_cleanup_module); diff --git a/trunk/drivers/net/cxgb3/cxgb3_offload.c b/trunk/drivers/net/cxgb3/cxgb3_offload.c deleted file mode 100644 index c3a02d613382..000000000000 --- a/trunk/drivers/net/cxgb3/cxgb3_offload.c +++ /dev/null @@ -1,1222 +0,0 @@ -/* - * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved. - * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "regs.h" -#include "cxgb3_ioctl.h" -#include "cxgb3_ctl_defs.h" -#include "cxgb3_defs.h" -#include "l2t.h" -#include "firmware_exports.h" -#include "cxgb3_offload.h" - -static LIST_HEAD(client_list); -static LIST_HEAD(ofld_dev_list); -static DEFINE_MUTEX(cxgb3_db_lock); - -static DEFINE_RWLOCK(adapter_list_lock); -static LIST_HEAD(adapter_list); - -static const unsigned int MAX_ATIDS = 64 * 1024; -static const unsigned int ATID_BASE = 0x100000; - -static inline int offload_activated(struct t3cdev *tdev) -{ - const struct adapter *adapter = tdev2adap(tdev); - - return (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)); -} - -/** - * cxgb3_register_client - register an offload client - * @client: the client - * - * Add the client to the client list, - * and call backs the client for each activated offload device - */ -void cxgb3_register_client(struct cxgb3_client *client) -{ - struct t3cdev *tdev; - - mutex_lock(&cxgb3_db_lock); - list_add_tail(&client->client_list, &client_list); - - if (client->add) { - list_for_each_entry(tdev, &ofld_dev_list, ofld_dev_list) { - if (offload_activated(tdev)) - client->add(tdev); - } - } - mutex_unlock(&cxgb3_db_lock); -} - -EXPORT_SYMBOL(cxgb3_register_client); - -/** - * cxgb3_unregister_client - unregister an offload client - * @client: the client - * - * Remove the client to the client list, - * and call backs the client for each activated offload device. - */ -void cxgb3_unregister_client(struct cxgb3_client *client) -{ - struct t3cdev *tdev; - - mutex_lock(&cxgb3_db_lock); - list_del(&client->client_list); - - if (client->remove) { - list_for_each_entry(tdev, &ofld_dev_list, ofld_dev_list) { - if (offload_activated(tdev)) - client->remove(tdev); - } - } - mutex_unlock(&cxgb3_db_lock); -} - -EXPORT_SYMBOL(cxgb3_unregister_client); - -/** - * cxgb3_add_clients - activate registered clients for an offload device - * @tdev: the offload device - * - * Call backs all registered clients once a offload device is activated - */ -void cxgb3_add_clients(struct t3cdev *tdev) -{ - struct cxgb3_client *client; - - mutex_lock(&cxgb3_db_lock); - list_for_each_entry(client, &client_list, client_list) { - if (client->add) - client->add(tdev); - } - mutex_unlock(&cxgb3_db_lock); -} - -/** - * cxgb3_remove_clients - deactivates registered clients - * for an offload device - * @tdev: the offload device - * - * Call backs all registered clients once a offload device is deactivated - */ -void cxgb3_remove_clients(struct t3cdev *tdev) -{ - struct cxgb3_client *client; - - mutex_lock(&cxgb3_db_lock); - list_for_each_entry(client, &client_list, client_list) { - if (client->remove) - client->remove(tdev); - } - mutex_unlock(&cxgb3_db_lock); -} - -static struct net_device *get_iff_from_mac(struct adapter *adapter, - const unsigned char *mac, - unsigned int vlan) -{ - int i; - - for_each_port(adapter, i) { - const struct vlan_group *grp; - struct net_device *dev = adapter->port[i]; - const struct port_info *p = netdev_priv(dev); - - if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) { - if (vlan && vlan != VLAN_VID_MASK) { - grp = p->vlan_grp; - dev = grp ? grp->vlan_devices[vlan] : NULL; - } else - while (dev->master) - dev = dev->master; - return dev; - } - } - return NULL; -} - -static int cxgb_ulp_iscsi_ctl(struct adapter *adapter, unsigned int req, - void *data) -{ - int ret = 0; - struct ulp_iscsi_info *uiip = data; - - switch (req) { - case ULP_ISCSI_GET_PARAMS: - uiip->pdev = adapter->pdev; - uiip->llimit = t3_read_reg(adapter, A_ULPRX_ISCSI_LLIMIT); - uiip->ulimit = t3_read_reg(adapter, A_ULPRX_ISCSI_ULIMIT); - uiip->tagmask = t3_read_reg(adapter, A_ULPRX_ISCSI_TAGMASK); - /* - * On tx, the iscsi pdu has to be <= tx page size and has to - * fit into the Tx PM FIFO. - */ - uiip->max_txsz = min(adapter->params.tp.tx_pg_size, - t3_read_reg(adapter, A_PM1_TX_CFG) >> 17); - /* on rx, the iscsi pdu has to be < rx page size and the - whole pdu + cpl headers has to fit into one sge buffer */ - uiip->max_rxsz = min_t(unsigned int, - adapter->params.tp.rx_pg_size, - (adapter->sge.qs[0].fl[1].buf_size - - sizeof(struct cpl_rx_data) * 2 - - sizeof(struct cpl_rx_data_ddp))); - break; - case ULP_ISCSI_SET_PARAMS: - t3_write_reg(adapter, A_ULPRX_ISCSI_TAGMASK, uiip->tagmask); - break; - default: - ret = -EOPNOTSUPP; - } - return ret; -} - -/* Response queue used for RDMA events. */ -#define ASYNC_NOTIF_RSPQ 0 - -static int cxgb_rdma_ctl(struct adapter *adapter, unsigned int req, void *data) -{ - int ret = 0; - - switch (req) { - case RDMA_GET_PARAMS:{ - struct rdma_info *req = data; - struct pci_dev *pdev = adapter->pdev; - - req->udbell_physbase = pci_resource_start(pdev, 2); - req->udbell_len = pci_resource_len(pdev, 2); - req->tpt_base = - t3_read_reg(adapter, A_ULPTX_TPT_LLIMIT); - req->tpt_top = t3_read_reg(adapter, A_ULPTX_TPT_ULIMIT); - req->pbl_base = - t3_read_reg(adapter, A_ULPTX_PBL_LLIMIT); - req->pbl_top = t3_read_reg(adapter, A_ULPTX_PBL_ULIMIT); - req->rqt_base = t3_read_reg(adapter, A_ULPRX_RQ_LLIMIT); - req->rqt_top = t3_read_reg(adapter, A_ULPRX_RQ_ULIMIT); - req->kdb_addr = adapter->regs + A_SG_KDOORBELL; - req->pdev = pdev; - break; - } - case RDMA_CQ_OP:{ - unsigned long flags; - struct rdma_cq_op *req = data; - - /* may be called in any context */ - spin_lock_irqsave(&adapter->sge.reg_lock, flags); - ret = t3_sge_cqcntxt_op(adapter, req->id, req->op, - req->credits); - spin_unlock_irqrestore(&adapter->sge.reg_lock, flags); - break; - } - case RDMA_GET_MEM:{ - struct ch_mem_range *t = data; - struct mc7 *mem; - - if ((t->addr & 7) || (t->len & 7)) - return -EINVAL; - if (t->mem_id == MEM_CM) - mem = &adapter->cm; - else if (t->mem_id == MEM_PMRX) - mem = &adapter->pmrx; - else if (t->mem_id == MEM_PMTX) - mem = &adapter->pmtx; - else - return -EINVAL; - - ret = - t3_mc7_bd_read(mem, t->addr / 8, t->len / 8, - (u64 *) t->buf); - if (ret) - return ret; - break; - } - case RDMA_CQ_SETUP:{ - struct rdma_cq_setup *req = data; - - spin_lock_irq(&adapter->sge.reg_lock); - ret = - t3_sge_init_cqcntxt(adapter, req->id, - req->base_addr, req->size, - ASYNC_NOTIF_RSPQ, - req->ovfl_mode, req->credits, - req->credit_thres); - spin_unlock_irq(&adapter->sge.reg_lock); - break; - } - case RDMA_CQ_DISABLE: - spin_lock_irq(&adapter->sge.reg_lock); - ret = t3_sge_disable_cqcntxt(adapter, *(unsigned int *)data); - spin_unlock_irq(&adapter->sge.reg_lock); - break; - case RDMA_CTRL_QP_SETUP:{ - struct rdma_ctrlqp_setup *req = data; - - spin_lock_irq(&adapter->sge.reg_lock); - ret = t3_sge_init_ecntxt(adapter, FW_RI_SGEEC_START, 0, - SGE_CNTXT_RDMA, - ASYNC_NOTIF_RSPQ, - req->base_addr, req->size, - FW_RI_TID_START, 1, 0); - spin_unlock_irq(&adapter->sge.reg_lock); - break; - } - default: - ret = -EOPNOTSUPP; - } - return ret; -} - -static int cxgb_offload_ctl(struct t3cdev *tdev, unsigned int req, void *data) -{ - struct adapter *adapter = tdev2adap(tdev); - struct tid_range *tid; - struct mtutab *mtup; - struct iff_mac *iffmacp; - struct ddp_params *ddpp; - struct adap_ports *ports; - int i; - - switch (req) { - case GET_MAX_OUTSTANDING_WR: - *(unsigned int *)data = FW_WR_NUM; - break; - case GET_WR_LEN: - *(unsigned int *)data = WR_FLITS; - break; - case GET_TX_MAX_CHUNK: - *(unsigned int *)data = 1 << 20; /* 1MB */ - break; - case GET_TID_RANGE: - tid = data; - tid->num = t3_mc5_size(&adapter->mc5) - - adapter->params.mc5.nroutes - - adapter->params.mc5.nfilters - adapter->params.mc5.nservers; - tid->base = 0; - break; - case GET_STID_RANGE: - tid = data; - tid->num = adapter->params.mc5.nservers; - tid->base = t3_mc5_size(&adapter->mc5) - tid->num - - adapter->params.mc5.nfilters - adapter->params.mc5.nroutes; - break; - case GET_L2T_CAPACITY: - *(unsigned int *)data = 2048; - break; - case GET_MTUS: - mtup = data; - mtup->size = NMTUS; - mtup->mtus = adapter->params.mtus; - break; - case GET_IFF_FROM_MAC: - iffmacp = data; - iffmacp->dev = get_iff_from_mac(adapter, iffmacp->mac_addr, - iffmacp->vlan_tag & - VLAN_VID_MASK); - break; - case GET_DDP_PARAMS: - ddpp = data; - ddpp->llimit = t3_read_reg(adapter, A_ULPRX_TDDP_LLIMIT); - ddpp->ulimit = t3_read_reg(adapter, A_ULPRX_TDDP_ULIMIT); - ddpp->tag_mask = t3_read_reg(adapter, A_ULPRX_TDDP_TAGMASK); - break; - case GET_PORTS: - ports = data; - ports->nports = adapter->params.nports; - for_each_port(adapter, i) - ports->lldevs[i] = adapter->port[i]; - break; - case ULP_ISCSI_GET_PARAMS: - case ULP_ISCSI_SET_PARAMS: - if (!offload_running(adapter)) - return -EAGAIN; - return cxgb_ulp_iscsi_ctl(adapter, req, data); - case RDMA_GET_PARAMS: - case RDMA_CQ_OP: - case RDMA_CQ_SETUP: - case RDMA_CQ_DISABLE: - case RDMA_CTRL_QP_SETUP: - case RDMA_GET_MEM: - if (!offload_running(adapter)) - return -EAGAIN; - return cxgb_rdma_ctl(adapter, req, data); - default: - return -EOPNOTSUPP; - } - return 0; -} - -/* - * Dummy handler for Rx offload packets in case we get an offload packet before - * proper processing is setup. This complains and drops the packet as it isn't - * normal to get offload packets at this stage. - */ -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)); - while (n--) - dev_kfree_skb_any(skbs[n]); - return 0; -} - -static void dummy_neigh_update(struct t3cdev *dev, struct neighbour *neigh) -{ -} - -void cxgb3_set_dummy_ops(struct t3cdev *dev) -{ - dev->recv = rx_offload_blackhole; - dev->neigh_update = dummy_neigh_update; -} - -/* - * Free an active-open TID. - */ -void *cxgb3_free_atid(struct t3cdev *tdev, int atid) -{ - struct tid_info *t = &(T3C_DATA(tdev))->tid_maps; - union active_open_entry *p = atid2entry(t, atid); - void *ctx = p->t3c_tid.ctx; - - spin_lock_bh(&t->atid_lock); - p->next = t->afree; - t->afree = p; - t->atids_in_use--; - spin_unlock_bh(&t->atid_lock); - - return ctx; -} - -EXPORT_SYMBOL(cxgb3_free_atid); - -/* - * Free a server TID and return it to the free pool. - */ -void cxgb3_free_stid(struct t3cdev *tdev, int stid) -{ - struct tid_info *t = &(T3C_DATA(tdev))->tid_maps; - union listen_entry *p = stid2entry(t, stid); - - spin_lock_bh(&t->stid_lock); - p->next = t->sfree; - t->sfree = p; - t->stids_in_use--; - spin_unlock_bh(&t->stid_lock); -} - -EXPORT_SYMBOL(cxgb3_free_stid); - -void cxgb3_insert_tid(struct t3cdev *tdev, struct cxgb3_client *client, - void *ctx, unsigned int tid) -{ - struct tid_info *t = &(T3C_DATA(tdev))->tid_maps; - - t->tid_tab[tid].client = client; - t->tid_tab[tid].ctx = ctx; - atomic_inc(&t->tids_in_use); -} - -EXPORT_SYMBOL(cxgb3_insert_tid); - -/* - * Populate a TID_RELEASE WR. The skb must be already propely sized. - */ -static inline void mk_tid_release(struct sk_buff *skb, unsigned int tid) -{ - struct cpl_tid_release *req; - - skb->priority = CPL_PRIORITY_SETUP; - req = (struct cpl_tid_release *)__skb_put(skb, sizeof(*req)); - req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); - OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, tid)); -} - -static void t3_process_tid_release_list(struct work_struct *work) -{ - struct t3c_data *td = container_of(work, struct t3c_data, - tid_release_task); - struct sk_buff *skb; - struct t3cdev *tdev = td->dev; - - - spin_lock_bh(&td->tid_release_lock); - while (td->tid_release_list) { - struct t3c_tid_entry *p = td->tid_release_list; - - td->tid_release_list = (struct t3c_tid_entry *)p->ctx; - spin_unlock_bh(&td->tid_release_lock); - - skb = alloc_skb(sizeof(struct cpl_tid_release), - GFP_KERNEL | __GFP_NOFAIL); - mk_tid_release(skb, p - td->tid_maps.tid_tab); - cxgb3_ofld_send(tdev, skb); - p->ctx = NULL; - spin_lock_bh(&td->tid_release_lock); - } - spin_unlock_bh(&td->tid_release_lock); -} - -/* use ctx as a next pointer in the tid release list */ -void cxgb3_queue_tid_release(struct t3cdev *tdev, unsigned int tid) -{ - struct t3c_data *td = T3C_DATA(tdev); - struct t3c_tid_entry *p = &td->tid_maps.tid_tab[tid]; - - spin_lock_bh(&td->tid_release_lock); - p->ctx = (void *)td->tid_release_list; - td->tid_release_list = p; - if (!p->ctx) - schedule_work(&td->tid_release_task); - spin_unlock_bh(&td->tid_release_lock); -} - -EXPORT_SYMBOL(cxgb3_queue_tid_release); - -/* - * Remove a tid from the TID table. A client may defer processing its last - * CPL message if it is locked at the time it arrives, and while the message - * sits in the client's backlog the TID may be reused for another connection. - * To handle this we atomically switch the TID association if it still points - * to the original client context. - */ -void cxgb3_remove_tid(struct t3cdev *tdev, void *ctx, unsigned int tid) -{ - struct tid_info *t = &(T3C_DATA(tdev))->tid_maps; - - BUG_ON(tid >= t->ntids); - if (tdev->type == T3A) - (void)cmpxchg(&t->tid_tab[tid].ctx, ctx, NULL); - else { - struct sk_buff *skb; - - skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_ATOMIC); - if (likely(skb)) { - mk_tid_release(skb, tid); - cxgb3_ofld_send(tdev, skb); - t->tid_tab[tid].ctx = NULL; - } else - cxgb3_queue_tid_release(tdev, tid); - } - atomic_dec(&t->tids_in_use); -} - -EXPORT_SYMBOL(cxgb3_remove_tid); - -int cxgb3_alloc_atid(struct t3cdev *tdev, struct cxgb3_client *client, - void *ctx) -{ - int atid = -1; - struct tid_info *t = &(T3C_DATA(tdev))->tid_maps; - - spin_lock_bh(&t->atid_lock); - if (t->afree) { - union active_open_entry *p = t->afree; - - atid = (p - t->atid_tab) + t->atid_base; - t->afree = p->next; - p->t3c_tid.ctx = ctx; - p->t3c_tid.client = client; - t->atids_in_use++; - } - spin_unlock_bh(&t->atid_lock); - return atid; -} - -EXPORT_SYMBOL(cxgb3_alloc_atid); - -int cxgb3_alloc_stid(struct t3cdev *tdev, struct cxgb3_client *client, - void *ctx) -{ - int stid = -1; - struct tid_info *t = &(T3C_DATA(tdev))->tid_maps; - - spin_lock_bh(&t->stid_lock); - if (t->sfree) { - union listen_entry *p = t->sfree; - - stid = (p - t->stid_tab) + t->stid_base; - t->sfree = p->next; - p->t3c_tid.ctx = ctx; - p->t3c_tid.client = client; - t->stids_in_use++; - } - spin_unlock_bh(&t->stid_lock); - return stid; -} - -EXPORT_SYMBOL(cxgb3_alloc_stid); - -static int do_smt_write_rpl(struct t3cdev *dev, struct sk_buff *skb) -{ - struct cpl_smt_write_rpl *rpl = cplhdr(skb); - - if (rpl->status != CPL_ERR_NONE) - printk(KERN_ERR - "Unexpected SMT_WRITE_RPL status %u for entry %u\n", - rpl->status, GET_TID(rpl)); - - return CPL_RET_BUF_DONE; -} - -static int do_l2t_write_rpl(struct t3cdev *dev, struct sk_buff *skb) -{ - struct cpl_l2t_write_rpl *rpl = cplhdr(skb); - - if (rpl->status != CPL_ERR_NONE) - printk(KERN_ERR - "Unexpected L2T_WRITE_RPL status %u for entry %u\n", - rpl->status, GET_TID(rpl)); - - return CPL_RET_BUF_DONE; -} - -static int do_act_open_rpl(struct t3cdev *dev, struct sk_buff *skb) -{ - struct cpl_act_open_rpl *rpl = cplhdr(skb); - unsigned int atid = G_TID(ntohl(rpl->atid)); - struct t3c_tid_entry *t3c_tid; - - t3c_tid = lookup_atid(&(T3C_DATA(dev))->tid_maps, atid); - if (t3c_tid->ctx && t3c_tid->client && t3c_tid->client->handlers && - t3c_tid->client->handlers[CPL_ACT_OPEN_RPL]) { - return t3c_tid->client->handlers[CPL_ACT_OPEN_RPL] (dev, skb, - t3c_tid-> - ctx); - } else { - printk(KERN_ERR "%s: received clientless CPL command 0x%x\n", - dev->name, CPL_ACT_OPEN_RPL); - return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG; - } -} - -static int do_stid_rpl(struct t3cdev *dev, struct sk_buff *skb) -{ - union opcode_tid *p = cplhdr(skb); - unsigned int stid = G_TID(ntohl(p->opcode_tid)); - struct t3c_tid_entry *t3c_tid; - - t3c_tid = lookup_stid(&(T3C_DATA(dev))->tid_maps, stid); - if (t3c_tid->ctx && t3c_tid->client->handlers && - t3c_tid->client->handlers[p->opcode]) { - return t3c_tid->client->handlers[p->opcode] (dev, skb, - t3c_tid->ctx); - } else { - printk(KERN_ERR "%s: received clientless CPL command 0x%x\n", - dev->name, p->opcode); - return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG; - } -} - -static int do_hwtid_rpl(struct t3cdev *dev, struct sk_buff *skb) -{ - union opcode_tid *p = cplhdr(skb); - unsigned int hwtid = G_TID(ntohl(p->opcode_tid)); - struct t3c_tid_entry *t3c_tid; - - t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid); - if (t3c_tid->ctx && t3c_tid->client->handlers && - t3c_tid->client->handlers[p->opcode]) { - return t3c_tid->client->handlers[p->opcode] - (dev, skb, t3c_tid->ctx); - } else { - printk(KERN_ERR "%s: received clientless CPL command 0x%x\n", - dev->name, p->opcode); - return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG; - } -} - -static int do_cr(struct t3cdev *dev, struct sk_buff *skb) -{ - struct cpl_pass_accept_req *req = cplhdr(skb); - unsigned int stid = G_PASS_OPEN_TID(ntohl(req->tos_tid)); - struct t3c_tid_entry *t3c_tid; - - t3c_tid = lookup_stid(&(T3C_DATA(dev))->tid_maps, stid); - if (t3c_tid->ctx && t3c_tid->client->handlers && - t3c_tid->client->handlers[CPL_PASS_ACCEPT_REQ]) { - return t3c_tid->client->handlers[CPL_PASS_ACCEPT_REQ] - (dev, skb, t3c_tid->ctx); - } else { - printk(KERN_ERR "%s: received clientless CPL command 0x%x\n", - dev->name, CPL_PASS_ACCEPT_REQ); - return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG; - } -} - -static int do_abort_req_rss(struct t3cdev *dev, struct sk_buff *skb) -{ - union opcode_tid *p = cplhdr(skb); - unsigned int hwtid = G_TID(ntohl(p->opcode_tid)); - struct t3c_tid_entry *t3c_tid; - - t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid); - if (t3c_tid->ctx && t3c_tid->client->handlers && - t3c_tid->client->handlers[p->opcode]) { - return t3c_tid->client->handlers[p->opcode] - (dev, skb, t3c_tid->ctx); - } else { - struct cpl_abort_req_rss *req = cplhdr(skb); - struct cpl_abort_rpl *rpl; - - struct sk_buff *skb = - alloc_skb(sizeof(struct cpl_abort_rpl), GFP_ATOMIC); - if (!skb) { - printk("do_abort_req_rss: couldn't get skb!\n"); - goto out; - } - skb->priority = CPL_PRIORITY_DATA; - __skb_put(skb, sizeof(struct cpl_abort_rpl)); - rpl = cplhdr(skb); - rpl->wr.wr_hi = - htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL)); - rpl->wr.wr_lo = htonl(V_WR_TID(GET_TID(req))); - OPCODE_TID(rpl) = - htonl(MK_OPCODE_TID(CPL_ABORT_RPL, GET_TID(req))); - rpl->cmd = req->status; - cxgb3_ofld_send(dev, skb); -out: - return CPL_RET_BUF_DONE; - } -} - -static int do_act_establish(struct t3cdev *dev, struct sk_buff *skb) -{ - struct cpl_act_establish *req = cplhdr(skb); - unsigned int atid = G_PASS_OPEN_TID(ntohl(req->tos_tid)); - struct t3c_tid_entry *t3c_tid; - - t3c_tid = lookup_atid(&(T3C_DATA(dev))->tid_maps, atid); - if (t3c_tid->ctx && t3c_tid->client->handlers && - t3c_tid->client->handlers[CPL_ACT_ESTABLISH]) { - return t3c_tid->client->handlers[CPL_ACT_ESTABLISH] - (dev, skb, t3c_tid->ctx); - } else { - printk(KERN_ERR "%s: received clientless CPL command 0x%x\n", - dev->name, CPL_PASS_ACCEPT_REQ); - return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG; - } -} - -static int do_set_tcb_rpl(struct t3cdev *dev, struct sk_buff *skb) -{ - struct cpl_set_tcb_rpl *rpl = cplhdr(skb); - - if (rpl->status != CPL_ERR_NONE) - printk(KERN_ERR - "Unexpected SET_TCB_RPL status %u for tid %u\n", - rpl->status, GET_TID(rpl)); - return CPL_RET_BUF_DONE; -} - -static int do_trace(struct t3cdev *dev, struct sk_buff *skb) -{ - struct cpl_trace_pkt *p = cplhdr(skb); - - skb->protocol = 0xffff; - skb->dev = dev->lldev; - skb_pull(skb, sizeof(*p)); - skb->mac.raw = skb->data; - netif_receive_skb(skb); - return 0; -} - -static int do_term(struct t3cdev *dev, struct sk_buff *skb) -{ - unsigned int hwtid = ntohl(skb->priority) >> 8 & 0xfffff; - unsigned int opcode = G_OPCODE(ntohl(skb->csum)); - struct t3c_tid_entry *t3c_tid; - - t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid); - if (t3c_tid->ctx && t3c_tid->client->handlers && - t3c_tid->client->handlers[opcode]) { - return t3c_tid->client->handlers[opcode] (dev, skb, - t3c_tid->ctx); - } else { - printk(KERN_ERR "%s: received clientless CPL command 0x%x\n", - dev->name, opcode); - return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG; - } -} - -static int nb_callback(struct notifier_block *self, unsigned long event, - void *ctx) -{ - switch (event) { - case (NETEVENT_NEIGH_UPDATE):{ - cxgb_neigh_update((struct neighbour *)ctx); - break; - } - case (NETEVENT_PMTU_UPDATE): - break; - case (NETEVENT_REDIRECT):{ - struct netevent_redirect *nr = ctx; - cxgb_redirect(nr->old, nr->new); - cxgb_neigh_update(nr->new->neighbour); - break; - } - default: - break; - } - return 0; -} - -static struct notifier_block nb = { - .notifier_call = nb_callback -}; - -/* - * Process a received packet with an unknown/unexpected CPL opcode. - */ -static int do_bad_cpl(struct t3cdev *dev, struct sk_buff *skb) -{ - printk(KERN_ERR "%s: received bad CPL command 0x%x\n", dev->name, - *skb->data); - return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG; -} - -/* - * Handlers for each CPL opcode - */ -static cpl_handler_func cpl_handlers[NUM_CPL_CMDS]; - -/* - * Add a new handler to the CPL dispatch table. A NULL handler may be supplied - * to unregister an existing handler. - */ -void t3_register_cpl_handler(unsigned int opcode, cpl_handler_func h) -{ - if (opcode < NUM_CPL_CMDS) - cpl_handlers[opcode] = h ? h : do_bad_cpl; - else - printk(KERN_ERR "T3C: handler registration for " - "opcode %x failed\n", opcode); -} - -EXPORT_SYMBOL(t3_register_cpl_handler); - -/* - * T3CDEV's receive method. - */ -int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n) -{ - while (n--) { - struct sk_buff *skb = *skbs++; - unsigned int opcode = G_OPCODE(ntohl(skb->csum)); - int ret = cpl_handlers[opcode] (dev, skb); - -#if VALIDATE_TID - if (ret & CPL_RET_UNKNOWN_TID) { - union opcode_tid *p = cplhdr(skb); - - printk(KERN_ERR "%s: CPL message (opcode %u) had " - "unknown TID %u\n", dev->name, opcode, - G_TID(ntohl(p->opcode_tid))); - } -#endif - if (ret & CPL_RET_BUF_DONE) - kfree_skb(skb); - } - return 0; -} - -/* - * Sends an sk_buff to a T3C driver after dealing with any active network taps. - */ -int cxgb3_ofld_send(struct t3cdev *dev, struct sk_buff *skb) -{ - int r; - - local_bh_disable(); - r = dev->send(dev, skb); - local_bh_enable(); - return r; -} - -EXPORT_SYMBOL(cxgb3_ofld_send); - -static int is_offloading(struct net_device *dev) -{ - struct adapter *adapter; - int i; - - read_lock_bh(&adapter_list_lock); - list_for_each_entry(adapter, &adapter_list, adapter_list) { - for_each_port(adapter, i) { - if (dev == adapter->port[i]) { - read_unlock_bh(&adapter_list_lock); - return 1; - } - } - } - read_unlock_bh(&adapter_list_lock); - return 0; -} - -void cxgb_neigh_update(struct neighbour *neigh) -{ - struct net_device *dev = neigh->dev; - - if (dev && (is_offloading(dev))) { - struct t3cdev *tdev = T3CDEV(dev); - - BUG_ON(!tdev); - t3_l2t_update(tdev, neigh); - } -} - -static void set_l2t_ix(struct t3cdev *tdev, u32 tid, struct l2t_entry *e) -{ - struct sk_buff *skb; - struct cpl_set_tcb_field *req; - - skb = alloc_skb(sizeof(*req), GFP_ATOMIC); - if (!skb) { - printk(KERN_ERR "%s: cannot allocate skb!\n", __FUNCTION__); - return; - } - skb->priority = CPL_PRIORITY_CONTROL; - req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req)); - req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); - OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); - req->reply = 0; - req->cpu_idx = 0; - req->word = htons(W_TCB_L2T_IX); - req->mask = cpu_to_be64(V_TCB_L2T_IX(M_TCB_L2T_IX)); - req->val = cpu_to_be64(V_TCB_L2T_IX(e->idx)); - tdev->send(tdev, skb); -} - -void cxgb_redirect(struct dst_entry *old, struct dst_entry *new) -{ - struct net_device *olddev, *newdev; - struct tid_info *ti; - struct t3cdev *tdev; - u32 tid; - int update_tcb; - struct l2t_entry *e; - struct t3c_tid_entry *te; - - olddev = old->neighbour->dev; - newdev = new->neighbour->dev; - if (!is_offloading(olddev)) - return; - if (!is_offloading(newdev)) { - printk(KERN_WARNING "%s: Redirect to non-offload" - "device ignored.\n", __FUNCTION__); - return; - } - tdev = T3CDEV(olddev); - BUG_ON(!tdev); - if (tdev != T3CDEV(newdev)) { - printk(KERN_WARNING "%s: Redirect to different " - "offload device ignored.\n", __FUNCTION__); - return; - } - - /* Add new L2T entry */ - e = t3_l2t_get(tdev, new->neighbour, newdev); - if (!e) { - printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n", - __FUNCTION__); - return; - } - - /* Walk tid table and notify clients of dst change. */ - ti = &(T3C_DATA(tdev))->tid_maps; - for (tid = 0; tid < ti->ntids; tid++) { - te = lookup_tid(ti, tid); - BUG_ON(!te); - if (te->ctx && te->client && te->client->redirect) { - update_tcb = te->client->redirect(te->ctx, old, new, e); - if (update_tcb) { - l2t_hold(L2DATA(tdev), e); - set_l2t_ix(tdev, tid, e); - } - } - } - l2t_release(L2DATA(tdev), e); -} - -/* - * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc. - * The allocated memory is cleared. - */ -void *cxgb_alloc_mem(unsigned long size) -{ - void *p = kmalloc(size, GFP_KERNEL); - - if (!p) - p = vmalloc(size); - if (p) - memset(p, 0, size); - return p; -} - -/* - * Free memory allocated through t3_alloc_mem(). - */ -void cxgb_free_mem(void *addr) -{ - unsigned long p = (unsigned long)addr; - - if (p >= VMALLOC_START && p < VMALLOC_END) - vfree(addr); - else - kfree(addr); -} - -/* - * Allocate and initialize the TID tables. Returns 0 on success. - */ -static int init_tid_tabs(struct tid_info *t, unsigned int ntids, - unsigned int natids, unsigned int nstids, - unsigned int atid_base, unsigned int stid_base) -{ - unsigned long size = ntids * sizeof(*t->tid_tab) + - natids * sizeof(*t->atid_tab) + nstids * sizeof(*t->stid_tab); - - t->tid_tab = cxgb_alloc_mem(size); - if (!t->tid_tab) - return -ENOMEM; - - t->stid_tab = (union listen_entry *)&t->tid_tab[ntids]; - t->atid_tab = (union active_open_entry *)&t->stid_tab[nstids]; - t->ntids = ntids; - t->nstids = nstids; - t->stid_base = stid_base; - t->sfree = NULL; - t->natids = natids; - t->atid_base = atid_base; - t->afree = NULL; - t->stids_in_use = t->atids_in_use = 0; - atomic_set(&t->tids_in_use, 0); - spin_lock_init(&t->stid_lock); - spin_lock_init(&t->atid_lock); - - /* - * Setup the free lists for stid_tab and atid_tab. - */ - if (nstids) { - while (--nstids) - t->stid_tab[nstids - 1].next = &t->stid_tab[nstids]; - t->sfree = t->stid_tab; - } - if (natids) { - while (--natids) - t->atid_tab[natids - 1].next = &t->atid_tab[natids]; - t->afree = t->atid_tab; - } - return 0; -} - -static void free_tid_maps(struct tid_info *t) -{ - cxgb_free_mem(t->tid_tab); -} - -static inline void add_adapter(struct adapter *adap) -{ - write_lock_bh(&adapter_list_lock); - list_add_tail(&adap->adapter_list, &adapter_list); - write_unlock_bh(&adapter_list_lock); -} - -static inline void remove_adapter(struct adapter *adap) -{ - write_lock_bh(&adapter_list_lock); - list_del(&adap->adapter_list); - write_unlock_bh(&adapter_list_lock); -} - -int cxgb3_offload_activate(struct adapter *adapter) -{ - struct t3cdev *dev = &adapter->tdev; - int natids, err; - struct t3c_data *t; - struct tid_range stid_range, tid_range; - struct mtutab mtutab; - unsigned int l2t_capacity; - - t = kcalloc(1, sizeof(*t), GFP_KERNEL); - if (!t) - return -ENOMEM; - - err = -EOPNOTSUPP; - if (dev->ctl(dev, GET_TX_MAX_CHUNK, &t->tx_max_chunk) < 0 || - dev->ctl(dev, GET_MAX_OUTSTANDING_WR, &t->max_wrs) < 0 || - dev->ctl(dev, GET_L2T_CAPACITY, &l2t_capacity) < 0 || - dev->ctl(dev, GET_MTUS, &mtutab) < 0 || - dev->ctl(dev, GET_TID_RANGE, &tid_range) < 0 || - dev->ctl(dev, GET_STID_RANGE, &stid_range) < 0) - goto out_free; - - err = -ENOMEM; - L2DATA(dev) = t3_init_l2t(l2t_capacity); - if (!L2DATA(dev)) - goto out_free; - - natids = min(tid_range.num / 2, MAX_ATIDS); - err = init_tid_tabs(&t->tid_maps, tid_range.num, natids, - stid_range.num, ATID_BASE, stid_range.base); - if (err) - goto out_free_l2t; - - t->mtus = mtutab.mtus; - t->nmtus = mtutab.size; - - INIT_WORK(&t->tid_release_task, t3_process_tid_release_list); - spin_lock_init(&t->tid_release_lock); - INIT_LIST_HEAD(&t->list_node); - t->dev = dev; - - T3C_DATA(dev) = t; - dev->recv = process_rx; - dev->neigh_update = t3_l2t_update; - - /* Register netevent handler once */ - if (list_empty(&adapter_list)) - register_netevent_notifier(&nb); - - add_adapter(adapter); - return 0; - -out_free_l2t: - t3_free_l2t(L2DATA(dev)); - L2DATA(dev) = NULL; -out_free: - kfree(t); - return err; -} - -void cxgb3_offload_deactivate(struct adapter *adapter) -{ - struct t3cdev *tdev = &adapter->tdev; - struct t3c_data *t = T3C_DATA(tdev); - - remove_adapter(adapter); - if (list_empty(&adapter_list)) - unregister_netevent_notifier(&nb); - - free_tid_maps(&t->tid_maps); - T3C_DATA(tdev) = NULL; - t3_free_l2t(L2DATA(tdev)); - L2DATA(tdev) = NULL; - kfree(t); -} - -static inline void register_tdev(struct t3cdev *tdev) -{ - static int unit; - - mutex_lock(&cxgb3_db_lock); - snprintf(tdev->name, sizeof(tdev->name), "ofld_dev%d", unit++); - list_add_tail(&tdev->ofld_dev_list, &ofld_dev_list); - mutex_unlock(&cxgb3_db_lock); -} - -static inline void unregister_tdev(struct t3cdev *tdev) -{ - mutex_lock(&cxgb3_db_lock); - list_del(&tdev->ofld_dev_list); - mutex_unlock(&cxgb3_db_lock); -} - -void __devinit cxgb3_adapter_ofld(struct adapter *adapter) -{ - struct t3cdev *tdev = &adapter->tdev; - - INIT_LIST_HEAD(&tdev->ofld_dev_list); - - cxgb3_set_dummy_ops(tdev); - tdev->send = t3_offload_tx; - tdev->ctl = cxgb_offload_ctl; - tdev->type = adapter->params.rev == 0 ? T3A : T3B; - - register_tdev(tdev); -} - -void __devexit cxgb3_adapter_unofld(struct adapter *adapter) -{ - struct t3cdev *tdev = &adapter->tdev; - - tdev->recv = NULL; - tdev->neigh_update = NULL; - - unregister_tdev(tdev); -} - -void __init cxgb3_offload_init(void) -{ - int i; - - for (i = 0; i < NUM_CPL_CMDS; ++i) - cpl_handlers[i] = do_bad_cpl; - - t3_register_cpl_handler(CPL_SMT_WRITE_RPL, do_smt_write_rpl); - t3_register_cpl_handler(CPL_L2T_WRITE_RPL, do_l2t_write_rpl); - t3_register_cpl_handler(CPL_PASS_OPEN_RPL, do_stid_rpl); - t3_register_cpl_handler(CPL_CLOSE_LISTSRV_RPL, do_stid_rpl); - t3_register_cpl_handler(CPL_PASS_ACCEPT_REQ, do_cr); - t3_register_cpl_handler(CPL_PASS_ESTABLISH, do_hwtid_rpl); - t3_register_cpl_handler(CPL_ABORT_RPL_RSS, do_hwtid_rpl); - t3_register_cpl_handler(CPL_ABORT_RPL, do_hwtid_rpl); - t3_register_cpl_handler(CPL_RX_URG_NOTIFY, do_hwtid_rpl); - t3_register_cpl_handler(CPL_RX_DATA, do_hwtid_rpl); - t3_register_cpl_handler(CPL_TX_DATA_ACK, do_hwtid_rpl); - t3_register_cpl_handler(CPL_TX_DMA_ACK, do_hwtid_rpl); - t3_register_cpl_handler(CPL_ACT_OPEN_RPL, do_act_open_rpl); - t3_register_cpl_handler(CPL_PEER_CLOSE, do_hwtid_rpl); - t3_register_cpl_handler(CPL_CLOSE_CON_RPL, do_hwtid_rpl); - t3_register_cpl_handler(CPL_ABORT_REQ_RSS, do_abort_req_rss); - t3_register_cpl_handler(CPL_ACT_ESTABLISH, do_act_establish); - t3_register_cpl_handler(CPL_SET_TCB_RPL, do_set_tcb_rpl); - t3_register_cpl_handler(CPL_RDMA_TERMINATE, do_term); - t3_register_cpl_handler(CPL_RDMA_EC_STATUS, do_hwtid_rpl); - t3_register_cpl_handler(CPL_TRACE_PKT, do_trace); - t3_register_cpl_handler(CPL_RX_DATA_DDP, do_hwtid_rpl); - t3_register_cpl_handler(CPL_RX_DDP_COMPLETE, do_hwtid_rpl); - t3_register_cpl_handler(CPL_ISCSI_HDR, do_hwtid_rpl); -} diff --git a/trunk/drivers/net/cxgb3/cxgb3_offload.h b/trunk/drivers/net/cxgb3/cxgb3_offload.h deleted file mode 100644 index 0e6beb69ba17..000000000000 --- a/trunk/drivers/net/cxgb3/cxgb3_offload.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2006-2007 Chelsio, Inc. All rights reserved. - * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _CXGB3_OFFLOAD_H -#define _CXGB3_OFFLOAD_H - -#include -#include - -#include "l2t.h" - -#include "t3cdev.h" -#include "t3_cpl.h" - -struct adapter; - -void cxgb3_offload_init(void); - -void cxgb3_adapter_ofld(struct adapter *adapter); -void cxgb3_adapter_unofld(struct adapter *adapter); -int cxgb3_offload_activate(struct adapter *adapter); -void cxgb3_offload_deactivate(struct adapter *adapter); - -void cxgb3_set_dummy_ops(struct t3cdev *dev); - -/* - * Client registration. Users of T3 driver must register themselves. - * The T3 driver will call the add function of every client for each T3 - * adapter activated, passing up the t3cdev ptr. Each client fills out an - * array of callback functions to process CPL messages. - */ - -void cxgb3_register_client(struct cxgb3_client *client); -void cxgb3_unregister_client(struct cxgb3_client *client); -void cxgb3_add_clients(struct t3cdev *tdev); -void cxgb3_remove_clients(struct t3cdev *tdev); - -typedef int (*cxgb3_cpl_handler_func)(struct t3cdev *dev, - struct sk_buff *skb, void *ctx); - -struct cxgb3_client { - char *name; - void (*add) (struct t3cdev *); - void (*remove) (struct t3cdev *); - cxgb3_cpl_handler_func *handlers; - int (*redirect)(void *ctx, struct dst_entry *old, - struct dst_entry *new, struct l2t_entry *l2t); - struct list_head client_list; -}; - -/* - * TID allocation services. - */ -int cxgb3_alloc_atid(struct t3cdev *dev, struct cxgb3_client *client, - void *ctx); -int cxgb3_alloc_stid(struct t3cdev *dev, struct cxgb3_client *client, - void *ctx); -void *cxgb3_free_atid(struct t3cdev *dev, int atid); -void cxgb3_free_stid(struct t3cdev *dev, int stid); -void cxgb3_insert_tid(struct t3cdev *dev, struct cxgb3_client *client, - void *ctx, unsigned int tid); -void cxgb3_queue_tid_release(struct t3cdev *dev, unsigned int tid); -void cxgb3_remove_tid(struct t3cdev *dev, void *ctx, unsigned int tid); - -struct t3c_tid_entry { - struct cxgb3_client *client; - void *ctx; -}; - -/* CPL message priority levels */ -enum { - CPL_PRIORITY_DATA = 0, /* data messages */ - CPL_PRIORITY_SETUP = 1, /* connection setup messages */ - CPL_PRIORITY_TEARDOWN = 0, /* connection teardown messages */ - CPL_PRIORITY_LISTEN = 1, /* listen start/stop messages */ - CPL_PRIORITY_ACK = 1, /* RX ACK messages */ - CPL_PRIORITY_CONTROL = 1 /* offload control messages */ -}; - -/* Flags for return value of CPL message handlers */ -enum { - CPL_RET_BUF_DONE = 1, /* buffer processing done, buffer may be freed */ - CPL_RET_BAD_MSG = 2, /* bad CPL message (e.g., unknown opcode) */ - CPL_RET_UNKNOWN_TID = 4 /* unexpected unknown TID */ -}; - -typedef int (*cpl_handler_func)(struct t3cdev *dev, struct sk_buff *skb); - -/* - * Returns a pointer to the first byte of the CPL header in an sk_buff that - * contains a CPL message. - */ -static inline void *cplhdr(struct sk_buff *skb) -{ - return skb->data; -} - -void t3_register_cpl_handler(unsigned int opcode, cpl_handler_func h); - -union listen_entry { - struct t3c_tid_entry t3c_tid; - union listen_entry *next; -}; - -union active_open_entry { - struct t3c_tid_entry t3c_tid; - union active_open_entry *next; -}; - -/* - * Holds the size, base address, free list start, etc of the TID, server TID, - * and active-open TID tables for a offload device. - * The tables themselves are allocated dynamically. - */ -struct tid_info { - struct t3c_tid_entry *tid_tab; - unsigned int ntids; - atomic_t tids_in_use; - - union listen_entry *stid_tab; - unsigned int nstids; - unsigned int stid_base; - - union active_open_entry *atid_tab; - unsigned int natids; - unsigned int atid_base; - - /* - * The following members are accessed R/W so we put them in their own - * cache lines. - * - * XXX We could combine the atid fields above with the lock here since - * atids are use once (unlike other tids). OTOH the above fields are - * usually in cache due to tid_tab. - */ - spinlock_t atid_lock ____cacheline_aligned_in_smp; - union active_open_entry *afree; - unsigned int atids_in_use; - - spinlock_t stid_lock ____cacheline_aligned; - union listen_entry *sfree; - unsigned int stids_in_use; -}; - -struct t3c_data { - struct list_head list_node; - struct t3cdev *dev; - unsigned int tx_max_chunk; /* max payload for TX_DATA */ - unsigned int max_wrs; /* max in-flight WRs per connection */ - unsigned int nmtus; - const unsigned short *mtus; - struct tid_info tid_maps; - - struct t3c_tid_entry *tid_release_list; - spinlock_t tid_release_lock; - struct work_struct tid_release_task; -}; - -/* - * t3cdev -> t3c_data accessor - */ -#define T3C_DATA(dev) (*(struct t3c_data **)&(dev)->l4opt) - -#endif diff --git a/trunk/drivers/net/cxgb3/firmware_exports.h b/trunk/drivers/net/cxgb3/firmware_exports.h deleted file mode 100644 index 6a835f6a262a..000000000000 --- a/trunk/drivers/net/cxgb3/firmware_exports.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2004-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _FIRMWARE_EXPORTS_H_ -#define _FIRMWARE_EXPORTS_H_ - -/* WR OPCODES supported by the firmware. - */ -#define FW_WROPCODE_FORWARD 0x01 -#define FW_WROPCODE_BYPASS 0x05 - -#define FW_WROPCODE_TUNNEL_TX_PKT 0x03 - -#define FW_WROPOCDE_ULPTX_DATA_SGL 0x00 -#define FW_WROPCODE_ULPTX_MEM_READ 0x02 -#define FW_WROPCODE_ULPTX_PKT 0x04 -#define FW_WROPCODE_ULPTX_INVALIDATE 0x06 - -#define FW_WROPCODE_TUNNEL_RX_PKT 0x07 - -#define FW_WROPCODE_OFLD_GETTCB_RPL 0x08 -#define FW_WROPCODE_OFLD_CLOSE_CON 0x09 -#define FW_WROPCODE_OFLD_TP_ABORT_CON_REQ 0x0A -#define FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL 0x0F -#define FW_WROPCODE_OFLD_HOST_ABORT_CON_REQ 0x0B -#define FW_WROPCODE_OFLD_TP_ABORT_CON_RPL 0x0C -#define FW_WROPCODE_OFLD_TX_DATA 0x0D -#define FW_WROPCODE_OFLD_TX_DATA_ACK 0x0E - -#define FW_WROPCODE_RI_RDMA_INIT 0x10 -#define FW_WROPCODE_RI_RDMA_WRITE 0x11 -#define FW_WROPCODE_RI_RDMA_READ_REQ 0x12 -#define FW_WROPCODE_RI_RDMA_READ_RESP 0x13 -#define FW_WROPCODE_RI_SEND 0x14 -#define FW_WROPCODE_RI_TERMINATE 0x15 -#define FW_WROPCODE_RI_RDMA_READ 0x16 -#define FW_WROPCODE_RI_RECEIVE 0x17 -#define FW_WROPCODE_RI_BIND_MW 0x18 -#define FW_WROPCODE_RI_FASTREGISTER_MR 0x19 -#define FW_WROPCODE_RI_LOCAL_INV 0x1A -#define FW_WROPCODE_RI_MODIFY_QP 0x1B -#define FW_WROPCODE_RI_BYPASS 0x1C - -#define FW_WROPOCDE_RSVD 0x1E - -#define FW_WROPCODE_SGE_EGRESSCONTEXT_RR 0x1F - -#define FW_WROPCODE_MNGT 0x1D -#define FW_MNGTOPCODE_PKTSCHED_SET 0x00 - -/* Maximum size of a WR sent from the host, limited by the SGE. - * - * Note: WR coming from ULP or TP are only limited by CIM. - */ -#define FW_WR_SIZE 128 - -/* Maximum number of outstanding WRs sent from the host. Value must be - * programmed in the CTRL/TUNNEL/QP SGE Egress Context and used by - * offload modules to limit the number of WRs per connection. - */ -#define FW_T3_WR_NUM 16 -#define FW_N3_WR_NUM 7 - -#ifndef N3 -# define FW_WR_NUM FW_T3_WR_NUM -#else -# define FW_WR_NUM FW_N3_WR_NUM -#endif - -/* FW_TUNNEL_NUM corresponds to the number of supported TUNNEL Queues. These - * queues must start at SGE Egress Context FW_TUNNEL_SGEEC_START and must - * start at 'TID' (or 'uP Token') FW_TUNNEL_TID_START. - * - * Ingress Traffic (e.g. DMA completion credit) for TUNNEL Queue[i] is sent - * to RESP Queue[i]. - */ -#define FW_TUNNEL_NUM 8 -#define FW_TUNNEL_SGEEC_START 8 -#define FW_TUNNEL_TID_START 65544 - -/* FW_CTRL_NUM corresponds to the number of supported CTRL Queues. These queues - * must start at SGE Egress Context FW_CTRL_SGEEC_START and must start at 'TID' - * (or 'uP Token') FW_CTRL_TID_START. - * - * Ingress Traffic for CTRL Queue[i] is sent to RESP Queue[i]. - */ -#define FW_CTRL_NUM 8 -#define FW_CTRL_SGEEC_START 65528 -#define FW_CTRL_TID_START 65536 - -/* FW_OFLD_NUM corresponds to the number of supported OFFLOAD Queues. These - * queues must start at SGE Egress Context FW_OFLD_SGEEC_START. - * - * Note: the 'uP Token' in the SGE Egress Context fields is irrelevant for - * OFFLOAD Queues, as the host is responsible for providing the correct TID in - * every WR. - * - * Ingress Trafffic for OFFLOAD Queue[i] is sent to RESP Queue[i]. - */ -#define FW_OFLD_NUM 8 -#define FW_OFLD_SGEEC_START 0 - -/* - * - */ -#define FW_RI_NUM 1 -#define FW_RI_SGEEC_START 65527 -#define FW_RI_TID_START 65552 - -/* - * The RX_PKT_TID - */ -#define FW_RX_PKT_NUM 1 -#define FW_RX_PKT_TID_START 65553 - -/* FW_WRC_NUM corresponds to the number of Work Request Context that supported - * by the firmware. - */ -#define FW_WRC_NUM \ - (65536 + FW_TUNNEL_NUM + FW_CTRL_NUM + FW_RI_NUM + FW_RX_PKT_NUM) - -/* - * FW type and version. - */ -#define S_FW_VERSION_TYPE 28 -#define M_FW_VERSION_TYPE 0xF -#define V_FW_VERSION_TYPE(x) ((x) << S_FW_VERSION_TYPE) -#define G_FW_VERSION_TYPE(x) \ - (((x) >> S_FW_VERSION_TYPE) & M_FW_VERSION_TYPE) - -#define S_FW_VERSION_MAJOR 16 -#define M_FW_VERSION_MAJOR 0xFFF -#define V_FW_VERSION_MAJOR(x) ((x) << S_FW_VERSION_MAJOR) -#define G_FW_VERSION_MAJOR(x) \ - (((x) >> S_FW_VERSION_MAJOR) & M_FW_VERSION_MAJOR) - -#define S_FW_VERSION_MINOR 8 -#define M_FW_VERSION_MINOR 0xFF -#define V_FW_VERSION_MINOR(x) ((x) << S_FW_VERSION_MINOR) -#define G_FW_VERSION_MINOR(x) \ - (((x) >> S_FW_VERSION_MINOR) & M_FW_VERSION_MINOR) - -#define S_FW_VERSION_MICRO 0 -#define M_FW_VERSION_MICRO 0xFF -#define V_FW_VERSION_MICRO(x) ((x) << S_FW_VERSION_MICRO) -#define G_FW_VERSION_MICRO(x) \ - (((x) >> S_FW_VERSION_MICRO) & M_FW_VERSION_MICRO) - -#endif /* _FIRMWARE_EXPORTS_H_ */ diff --git a/trunk/drivers/net/cxgb3/l2t.c b/trunk/drivers/net/cxgb3/l2t.c deleted file mode 100644 index 3c0cb8557058..000000000000 --- a/trunk/drivers/net/cxgb3/l2t.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. - * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include "common.h" -#include "t3cdev.h" -#include "cxgb3_defs.h" -#include "l2t.h" -#include "t3_cpl.h" -#include "firmware_exports.h" - -#define VLAN_NONE 0xfff - -/* - * Module locking notes: There is a RW lock protecting the L2 table as a - * whole plus a spinlock per L2T entry. Entry lookups and allocations happen - * under the protection of the table lock, individual entry changes happen - * while holding that entry's spinlock. The table lock nests outside the - * entry locks. Allocations of new entries take the table lock as writers so - * no other lookups can happen while allocating new entries. Entry updates - * take the table lock as readers so multiple entries can be updated in - * parallel. An L2T entry can be dropped by decrementing its reference count - * and therefore can happen in parallel with entry allocation but no entry - * can change state or increment its ref count during allocation as both of - * these perform lookups. - */ - -static inline unsigned int vlan_prio(const struct l2t_entry *e) -{ - return e->vlan >> 13; -} - -static inline unsigned int arp_hash(u32 key, int ifindex, - const struct l2t_data *d) -{ - return jhash_2words(key, ifindex, 0) & (d->nentries - 1); -} - -static inline void neigh_replace(struct l2t_entry *e, struct neighbour *n) -{ - neigh_hold(n); - if (e->neigh) - neigh_release(e->neigh); - e->neigh = n; -} - -/* - * Set up an L2T entry and send any packets waiting in the arp queue. The - * supplied skb is used for the CPL_L2T_WRITE_REQ. Must be called with the - * entry locked. - */ -static int setup_l2e_send_pending(struct t3cdev *dev, struct sk_buff *skb, - struct l2t_entry *e) -{ - struct cpl_l2t_write_req *req; - - if (!skb) { - skb = alloc_skb(sizeof(*req), GFP_ATOMIC); - if (!skb) - return -ENOMEM; - } - - req = (struct cpl_l2t_write_req *)__skb_put(skb, sizeof(*req)); - req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); - OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, e->idx)); - req->params = htonl(V_L2T_W_IDX(e->idx) | V_L2T_W_IFF(e->smt_idx) | - V_L2T_W_VLAN(e->vlan & VLAN_VID_MASK) | - V_L2T_W_PRIO(vlan_prio(e))); - memcpy(e->dmac, e->neigh->ha, sizeof(e->dmac)); - memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac)); - skb->priority = CPL_PRIORITY_CONTROL; - cxgb3_ofld_send(dev, skb); - while (e->arpq_head) { - skb = e->arpq_head; - e->arpq_head = skb->next; - skb->next = NULL; - cxgb3_ofld_send(dev, skb); - } - e->arpq_tail = NULL; - e->state = L2T_STATE_VALID; - - return 0; -} - -/* - * Add a packet to the an L2T entry's queue of packets awaiting resolution. - * Must be called with the entry's lock held. - */ -static inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb) -{ - skb->next = NULL; - if (e->arpq_head) - e->arpq_tail->next = skb; - else - e->arpq_head = skb; - e->arpq_tail = skb; -} - -int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb, - struct l2t_entry *e) -{ -again: - switch (e->state) { - case L2T_STATE_STALE: /* entry is stale, kick off revalidation */ - neigh_event_send(e->neigh, NULL); - spin_lock_bh(&e->lock); - if (e->state == L2T_STATE_STALE) - e->state = L2T_STATE_VALID; - spin_unlock_bh(&e->lock); - case L2T_STATE_VALID: /* fast-path, send the packet on */ - return cxgb3_ofld_send(dev, skb); - case L2T_STATE_RESOLVING: - spin_lock_bh(&e->lock); - if (e->state != L2T_STATE_RESOLVING) { - /* ARP already completed */ - spin_unlock_bh(&e->lock); - goto again; - } - arpq_enqueue(e, skb); - spin_unlock_bh(&e->lock); - - /* - * Only the first packet added to the arpq should kick off - * resolution. However, because the alloc_skb below can fail, - * we allow each packet added to the arpq to retry resolution - * as a way of recovering from transient memory exhaustion. - * A better way would be to use a work request to retry L2T - * entries when there's no memory. - */ - if (!neigh_event_send(e->neigh, NULL)) { - skb = alloc_skb(sizeof(struct cpl_l2t_write_req), - GFP_ATOMIC); - if (!skb) - break; - - spin_lock_bh(&e->lock); - if (e->arpq_head) - setup_l2e_send_pending(dev, skb, e); - else /* we lost the race */ - __kfree_skb(skb); - spin_unlock_bh(&e->lock); - } - } - return 0; -} - -EXPORT_SYMBOL(t3_l2t_send_slow); - -void t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e) -{ -again: - switch (e->state) { - case L2T_STATE_STALE: /* entry is stale, kick off revalidation */ - neigh_event_send(e->neigh, NULL); - spin_lock_bh(&e->lock); - if (e->state == L2T_STATE_STALE) { - e->state = L2T_STATE_VALID; - } - spin_unlock_bh(&e->lock); - return; - case L2T_STATE_VALID: /* fast-path, send the packet on */ - return; - case L2T_STATE_RESOLVING: - spin_lock_bh(&e->lock); - if (e->state != L2T_STATE_RESOLVING) { - /* ARP already completed */ - spin_unlock_bh(&e->lock); - goto again; - } - spin_unlock_bh(&e->lock); - - /* - * Only the first packet added to the arpq should kick off - * resolution. However, because the alloc_skb below can fail, - * we allow each packet added to the arpq to retry resolution - * as a way of recovering from transient memory exhaustion. - * A better way would be to use a work request to retry L2T - * entries when there's no memory. - */ - neigh_event_send(e->neigh, NULL); - } - return; -} - -EXPORT_SYMBOL(t3_l2t_send_event); - -/* - * Allocate a free L2T entry. Must be called with l2t_data.lock held. - */ -static struct l2t_entry *alloc_l2e(struct l2t_data *d) -{ - struct l2t_entry *end, *e, **p; - - if (!atomic_read(&d->nfree)) - return NULL; - - /* there's definitely a free entry */ - for (e = d->rover, end = &d->l2tab[d->nentries]; e != end; ++e) - if (atomic_read(&e->refcnt) == 0) - goto found; - - for (e = &d->l2tab[1]; atomic_read(&e->refcnt); ++e) ; -found: - d->rover = e + 1; - atomic_dec(&d->nfree); - - /* - * The entry we found may be an inactive entry that is - * presently in the hash table. We need to remove it. - */ - if (e->state != L2T_STATE_UNUSED) { - int hash = arp_hash(e->addr, e->ifindex, d); - - for (p = &d->l2tab[hash].first; *p; p = &(*p)->next) - if (*p == e) { - *p = e->next; - break; - } - e->state = L2T_STATE_UNUSED; - } - return e; -} - -/* - * Called when an L2T entry has no more users. The entry is left in the hash - * table since it is likely to be reused but we also bump nfree to indicate - * that the entry can be reallocated for a different neighbor. We also drop - * the existing neighbor reference in case the neighbor is going away and is - * waiting on our reference. - * - * Because entries can be reallocated to other neighbors once their ref count - * drops to 0 we need to take the entry's lock to avoid races with a new - * incarnation. - */ -void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e) -{ - spin_lock_bh(&e->lock); - if (atomic_read(&e->refcnt) == 0) { /* hasn't been recycled */ - if (e->neigh) { - neigh_release(e->neigh); - e->neigh = NULL; - } - } - spin_unlock_bh(&e->lock); - atomic_inc(&d->nfree); -} - -EXPORT_SYMBOL(t3_l2e_free); - -/* - * Update an L2T entry that was previously used for the same next hop as neigh. - * Must be called with softirqs disabled. - */ -static inline void reuse_entry(struct l2t_entry *e, struct neighbour *neigh) -{ - unsigned int nud_state; - - spin_lock(&e->lock); /* avoid race with t3_l2t_free */ - - if (neigh != e->neigh) - neigh_replace(e, neigh); - nud_state = neigh->nud_state; - if (memcmp(e->dmac, neigh->ha, sizeof(e->dmac)) || - !(nud_state & NUD_VALID)) - e->state = L2T_STATE_RESOLVING; - else if (nud_state & NUD_CONNECTED) - e->state = L2T_STATE_VALID; - else - e->state = L2T_STATE_STALE; - spin_unlock(&e->lock); -} - -struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh, - struct net_device *dev) -{ - struct l2t_entry *e; - struct l2t_data *d = L2DATA(cdev); - u32 addr = *(u32 *) neigh->primary_key; - int ifidx = neigh->dev->ifindex; - int hash = arp_hash(addr, ifidx, d); - struct port_info *p = netdev_priv(dev); - int smt_idx = p->port_id; - - write_lock_bh(&d->lock); - for (e = d->l2tab[hash].first; e; e = e->next) - if (e->addr == addr && e->ifindex == ifidx && - e->smt_idx == smt_idx) { - l2t_hold(d, e); - if (atomic_read(&e->refcnt) == 1) - reuse_entry(e, neigh); - goto done; - } - - /* Need to allocate a new entry */ - e = alloc_l2e(d); - if (e) { - spin_lock(&e->lock); /* avoid race with t3_l2t_free */ - e->next = d->l2tab[hash].first; - d->l2tab[hash].first = e; - e->state = L2T_STATE_RESOLVING; - e->addr = addr; - e->ifindex = ifidx; - e->smt_idx = smt_idx; - atomic_set(&e->refcnt, 1); - neigh_replace(e, neigh); - if (neigh->dev->priv_flags & IFF_802_1Q_VLAN) - e->vlan = VLAN_DEV_INFO(neigh->dev)->vlan_id; - else - e->vlan = VLAN_NONE; - spin_unlock(&e->lock); - } -done: - write_unlock_bh(&d->lock); - return e; -} - -EXPORT_SYMBOL(t3_l2t_get); - -/* - * Called when address resolution fails for an L2T entry to handle packets - * on the arpq head. If a packet specifies a failure handler it is invoked, - * otherwise the packets is sent to the offload device. - * - * XXX: maybe we should abandon the latter behavior and just require a failure - * handler. - */ -static void handle_failed_resolution(struct t3cdev *dev, struct sk_buff *arpq) -{ - while (arpq) { - struct sk_buff *skb = arpq; - struct l2t_skb_cb *cb = L2T_SKB_CB(skb); - - arpq = skb->next; - skb->next = NULL; - if (cb->arp_failure_handler) - cb->arp_failure_handler(dev, skb); - else - cxgb3_ofld_send(dev, skb); - } -} - -/* - * Called when the host's ARP layer makes a change to some entry that is - * loaded into the HW L2 table. - */ -void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh) -{ - struct l2t_entry *e; - struct sk_buff *arpq = NULL; - struct l2t_data *d = L2DATA(dev); - u32 addr = *(u32 *) neigh->primary_key; - int ifidx = neigh->dev->ifindex; - int hash = arp_hash(addr, ifidx, d); - - read_lock_bh(&d->lock); - for (e = d->l2tab[hash].first; e; e = e->next) - if (e->addr == addr && e->ifindex == ifidx) { - spin_lock(&e->lock); - goto found; - } - read_unlock_bh(&d->lock); - return; - -found: - read_unlock(&d->lock); - if (atomic_read(&e->refcnt)) { - if (neigh != e->neigh) - neigh_replace(e, neigh); - - if (e->state == L2T_STATE_RESOLVING) { - if (neigh->nud_state & NUD_FAILED) { - arpq = e->arpq_head; - e->arpq_head = e->arpq_tail = NULL; - } else if (neigh_is_connected(neigh)) - setup_l2e_send_pending(dev, NULL, e); - } else { - e->state = neigh_is_connected(neigh) ? - L2T_STATE_VALID : L2T_STATE_STALE; - if (memcmp(e->dmac, neigh->ha, 6)) - setup_l2e_send_pending(dev, NULL, e); - } - } - spin_unlock_bh(&e->lock); - - if (arpq) - handle_failed_resolution(dev, arpq); -} - -struct l2t_data *t3_init_l2t(unsigned int l2t_capacity) -{ - struct l2t_data *d; - int i, size = sizeof(*d) + l2t_capacity * sizeof(struct l2t_entry); - - d = cxgb_alloc_mem(size); - if (!d) - return NULL; - - d->nentries = l2t_capacity; - d->rover = &d->l2tab[1]; /* entry 0 is not used */ - atomic_set(&d->nfree, l2t_capacity - 1); - rwlock_init(&d->lock); - - for (i = 0; i < l2t_capacity; ++i) { - d->l2tab[i].idx = i; - d->l2tab[i].state = L2T_STATE_UNUSED; - spin_lock_init(&d->l2tab[i].lock); - atomic_set(&d->l2tab[i].refcnt, 0); - } - return d; -} - -void t3_free_l2t(struct l2t_data *d) -{ - cxgb_free_mem(d); -} - diff --git a/trunk/drivers/net/cxgb3/l2t.h b/trunk/drivers/net/cxgb3/l2t.h deleted file mode 100644 index ba5d2cbd7241..000000000000 --- a/trunk/drivers/net/cxgb3/l2t.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. - * Copyright (c) 2006-2007 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _CHELSIO_L2T_H -#define _CHELSIO_L2T_H - -#include -#include "t3cdev.h" -#include - -enum { - L2T_STATE_VALID, /* entry is up to date */ - L2T_STATE_STALE, /* entry may be used but needs revalidation */ - L2T_STATE_RESOLVING, /* entry needs address resolution */ - L2T_STATE_UNUSED /* entry not in use */ -}; - -struct neighbour; -struct sk_buff; - -/* - * Each L2T entry plays multiple roles. First of all, it keeps state for the - * corresponding entry of the HW L2 table and maintains a queue of offload - * packets awaiting address resolution. Second, it is a node of a hash table - * chain, where the nodes of the chain are linked together through their next - * pointer. Finally, each node is a bucket of a hash table, pointing to the - * first element in its chain through its first pointer. - */ -struct l2t_entry { - u16 state; /* entry state */ - u16 idx; /* entry index */ - u32 addr; /* dest IP address */ - int ifindex; /* neighbor's net_device's ifindex */ - u16 smt_idx; /* SMT index */ - u16 vlan; /* VLAN TCI (id: bits 0-11, prio: 13-15 */ - struct neighbour *neigh; /* associated neighbour */ - struct l2t_entry *first; /* start of hash chain */ - struct l2t_entry *next; /* next l2t_entry on chain */ - struct sk_buff *arpq_head; /* queue of packets awaiting resolution */ - struct sk_buff *arpq_tail; - spinlock_t lock; - atomic_t refcnt; /* entry reference count */ - u8 dmac[6]; /* neighbour's MAC address */ -}; - -struct l2t_data { - unsigned int nentries; /* number of entries */ - struct l2t_entry *rover; /* starting point for next allocation */ - atomic_t nfree; /* number of free entries */ - rwlock_t lock; - struct l2t_entry l2tab[0]; -}; - -typedef void (*arp_failure_handler_func)(struct t3cdev * dev, - struct sk_buff * skb); - -/* - * Callback stored in an skb to handle address resolution failure. - */ -struct l2t_skb_cb { - arp_failure_handler_func arp_failure_handler; -}; - -#define L2T_SKB_CB(skb) ((struct l2t_skb_cb *)(skb)->cb) - -static inline void set_arp_failure_handler(struct sk_buff *skb, - arp_failure_handler_func hnd) -{ - L2T_SKB_CB(skb)->arp_failure_handler = hnd; -} - -/* - * Getting to the L2 data from an offload device. - */ -#define L2DATA(dev) ((dev)->l2opt) - -#define W_TCB_L2T_IX 0 -#define S_TCB_L2T_IX 7 -#define M_TCB_L2T_IX 0x7ffULL -#define V_TCB_L2T_IX(x) ((x) << S_TCB_L2T_IX) - -void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e); -void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh); -struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh, - struct net_device *dev); -int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb, - struct l2t_entry *e); -void t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e); -struct l2t_data *t3_init_l2t(unsigned int l2t_capacity); -void t3_free_l2t(struct l2t_data *d); - -int cxgb3_ofld_send(struct t3cdev *dev, struct sk_buff *skb); - -static inline int l2t_send(struct t3cdev *dev, struct sk_buff *skb, - struct l2t_entry *e) -{ - if (likely(e->state == L2T_STATE_VALID)) - return cxgb3_ofld_send(dev, skb); - return t3_l2t_send_slow(dev, skb, e); -} - -static inline void l2t_release(struct l2t_data *d, struct l2t_entry *e) -{ - if (atomic_dec_and_test(&e->refcnt)) - t3_l2e_free(d, e); -} - -static inline void l2t_hold(struct l2t_data *d, struct l2t_entry *e) -{ - if (atomic_add_return(1, &e->refcnt) == 1) /* 0 -> 1 transition */ - atomic_dec(&d->nfree); -} - -#endif diff --git a/trunk/drivers/net/cxgb3/mc5.c b/trunk/drivers/net/cxgb3/mc5.c deleted file mode 100644 index 644d62ea86a6..000000000000 --- a/trunk/drivers/net/cxgb3/mc5.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "common.h" -#include "regs.h" - -enum { - IDT75P52100 = 4, - IDT75N43102 = 5 -}; - -/* DBGI command mode */ -enum { - DBGI_MODE_MBUS = 0, - DBGI_MODE_IDT52100 = 5 -}; - -/* IDT 75P52100 commands */ -#define IDT_CMD_READ 0 -#define IDT_CMD_WRITE 1 -#define IDT_CMD_SEARCH 2 -#define IDT_CMD_LEARN 3 - -/* IDT LAR register address and value for 144-bit mode (low 32 bits) */ -#define IDT_LAR_ADR0 0x180006 -#define IDT_LAR_MODE144 0xffff0000 - -/* IDT SCR and SSR addresses (low 32 bits) */ -#define IDT_SCR_ADR0 0x180000 -#define IDT_SSR0_ADR0 0x180002 -#define IDT_SSR1_ADR0 0x180004 - -/* IDT GMR base address (low 32 bits) */ -#define IDT_GMR_BASE_ADR0 0x180020 - -/* IDT data and mask array base addresses (low 32 bits) */ -#define IDT_DATARY_BASE_ADR0 0 -#define IDT_MSKARY_BASE_ADR0 0x80000 - -/* IDT 75N43102 commands */ -#define IDT4_CMD_SEARCH144 3 -#define IDT4_CMD_WRITE 4 -#define IDT4_CMD_READ 5 - -/* IDT 75N43102 SCR address (low 32 bits) */ -#define IDT4_SCR_ADR0 0x3 - -/* IDT 75N43102 GMR base addresses (low 32 bits) */ -#define IDT4_GMR_BASE0 0x10 -#define IDT4_GMR_BASE1 0x20 -#define IDT4_GMR_BASE2 0x30 - -/* IDT 75N43102 data and mask array base addresses (low 32 bits) */ -#define IDT4_DATARY_BASE_ADR0 0x1000000 -#define IDT4_MSKARY_BASE_ADR0 0x2000000 - -#define MAX_WRITE_ATTEMPTS 5 - -#define MAX_ROUTES 2048 - -/* - * Issue a command to the TCAM and wait for its completion. The address and - * any data required by the command must have been setup by the caller. - */ -static int mc5_cmd_write(struct adapter *adapter, u32 cmd) -{ - t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd); - return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS, - F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1); -} - -static inline void dbgi_wr_addr3(struct adapter *adapter, u32 v1, u32 v2, - u32 v3) -{ - t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, v1); - t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR1, v2); - t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR2, v3); -} - -static inline void dbgi_wr_data3(struct adapter *adapter, u32 v1, u32 v2, - u32 v3) -{ - t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1); - t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2); - t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3); -} - -static inline void dbgi_rd_rsp3(struct adapter *adapter, u32 *v1, u32 *v2, - u32 *v3) -{ - *v1 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA0); - *v2 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA1); - *v3 = t3_read_reg(adapter, A_MC5_DB_DBGI_RSP_DATA2); -} - -/* - * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM - * command cmd. The data to be written must have been set up by the caller. - * Returns -1 on failure, 0 on success. - */ -static int mc5_write(struct adapter *adapter, u32 addr_lo, u32 cmd) -{ - t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo); - if (mc5_cmd_write(adapter, cmd) == 0) - return 0; - CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n", - addr_lo); - return -1; -} - -static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base, - u32 data_array_base, u32 write_cmd, - int addr_shift) -{ - unsigned int i; - struct adapter *adap = mc5->adapter; - - /* - * We need the size of the TCAM data and mask arrays in terms of - * 72-bit entries. - */ - unsigned int size72 = mc5->tcam_size; - unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX); - - if (mc5->mode == MC5_MODE_144_BIT) { - size72 *= 2; /* 1 144-bit entry is 2 72-bit entries */ - server_base *= 2; - } - - /* Clear the data array */ - dbgi_wr_data3(adap, 0, 0, 0); - for (i = 0; i < size72; i++) - if (mc5_write(adap, data_array_base + (i << addr_shift), - write_cmd)) - return -1; - - /* Initialize the mask array. */ - dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff); - for (i = 0; i < size72; i++) { - if (i == server_base) /* entering server or routing region */ - t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0, - mc5->mode == MC5_MODE_144_BIT ? - 0xfffffff9 : 0xfffffffd); - if (mc5_write(adap, mask_array_base + (i << addr_shift), - write_cmd)) - return -1; - } - return 0; -} - -static int init_idt52100(struct mc5 *mc5) -{ - int i; - struct adapter *adap = mc5->adapter; - - t3_write_reg(adap, A_MC5_DB_RSP_LATENCY, - V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15)); - t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2); - - /* - * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and - * GMRs 8-9 for ACK- and AOPEN searches. - */ - t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE); - t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE); - t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH); - t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN); - t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000); - t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN); - t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH); - t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN); - t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH); - t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000); - t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE); - t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ); - - /* Set DBGI command mode for IDT TCAM. */ - t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100); - - /* Set up LAR */ - dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0); - if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE)) - goto err; - - /* Set up SSRs */ - dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0); - if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) || - mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE)) - goto err; - - /* Set up GMRs */ - for (i = 0; i < 32; ++i) { - if (i >= 12 && i < 15) - dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff); - else if (i == 15) - dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff); - else - dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff); - - if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE)) - goto err; - } - - /* Set up SCR */ - dbgi_wr_data3(adap, 1, 0, 0); - if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE)) - goto err; - - return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0, - IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0); -err: - return -EIO; -} - -static int init_idt43102(struct mc5 *mc5) -{ - int i; - struct adapter *adap = mc5->adapter; - - t3_write_reg(adap, A_MC5_DB_RSP_LATENCY, - adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) : - V_RDLAT(0xd) | V_SRCHLAT(0x12)); - - /* - * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask - * for ACK- and AOPEN searches. - */ - t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE); - t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE); - t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, - IDT4_CMD_SEARCH144 | 0x3800); - t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144); - t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800); - t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800); - t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800); - t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE); - t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ); - - t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3); - - /* Set DBGI command mode for IDT TCAM. */ - t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100); - - /* Set up GMRs */ - dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff); - for (i = 0; i < 7; ++i) - if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE)) - goto err; - - for (i = 0; i < 4; ++i) - if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE)) - goto err; - - dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff); - if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) || - mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) || - mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE)) - goto err; - - dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff); - if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE)) - goto err; - - /* Set up SCR */ - dbgi_wr_data3(adap, 0xf0000000, 0, 0); - if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE)) - goto err; - - return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0, - IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1); -err: - return -EIO; -} - -/* Put MC5 in DBGI mode. */ -static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5) -{ - t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG, - V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN); -} - -/* Put MC5 in M-Bus mode. */ -static void mc5_dbgi_mode_disable(const struct mc5 *mc5) -{ - t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG, - V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | - V_COMPEN(mc5->mode == MC5_MODE_72_BIT) | - V_PRTYEN(mc5->parity_enabled) | F_MBUSEN); -} - -/* - * Initialization that requires the OS and protocol layers to already - * be intialized goes here. - */ -int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, - unsigned int nroutes) -{ - u32 cfg; - int err; - unsigned int tcam_size = mc5->tcam_size; - struct adapter *adap = mc5->adapter; - - if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size) - return -EINVAL; - - /* Reset the TCAM */ - cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE; - cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST; - t3_write_reg(adap, A_MC5_DB_CONFIG, cfg); - if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) { - CH_ERR(adap, "TCAM reset timed out\n"); - return -1; - } - - t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes); - t3_write_reg(adap, A_MC5_DB_FILTER_TABLE, - tcam_size - nroutes - nfilters); - t3_write_reg(adap, A_MC5_DB_SERVER_INDEX, - tcam_size - nroutes - nfilters - nservers); - - mc5->parity_enabled = 1; - - /* All the TCAM addresses we access have only the low 32 bits non 0 */ - t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0); - t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0); - - mc5_dbgi_mode_enable(mc5); - - switch (mc5->part_type) { - case IDT75P52100: - err = init_idt52100(mc5); - break; - case IDT75N43102: - err = init_idt43102(mc5); - break; - default: - CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type); - err = -EINVAL; - break; - } - - mc5_dbgi_mode_disable(mc5); - return err; -} - -/* - * read_mc5_range - dump a part of the memory managed by MC5 - * @mc5: the MC5 handle - * @start: the start address for the dump - * @n: number of 72-bit words to read - * @buf: result buffer - * - * Read n 72-bit words from MC5 memory from the given start location. - */ -int t3_read_mc5_range(const struct mc5 *mc5, unsigned int start, - unsigned int n, u32 *buf) -{ - u32 read_cmd; - int err = 0; - struct adapter *adap = mc5->adapter; - - if (mc5->part_type == IDT75P52100) - read_cmd = IDT_CMD_READ; - else if (mc5->part_type == IDT75N43102) - read_cmd = IDT4_CMD_READ; - else - return -EINVAL; - - mc5_dbgi_mode_enable(mc5); - - while (n--) { - t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR0, start++); - if (mc5_cmd_write(adap, read_cmd)) { - err = -EIO; - break; - } - dbgi_rd_rsp3(adap, buf + 2, buf + 1, buf); - buf += 3; - } - - mc5_dbgi_mode_disable(mc5); - return 0; -} - -#define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR) - -/* - * MC5 interrupt handler - */ -void t3_mc5_intr_handler(struct mc5 *mc5) -{ - struct adapter *adap = mc5->adapter; - u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE); - - if ((cause & F_PARITYERR) && mc5->parity_enabled) { - CH_ALERT(adap, "MC5 parity error\n"); - mc5->stats.parity_err++; - } - - if (cause & F_REQQPARERR) { - CH_ALERT(adap, "MC5 request queue parity error\n"); - mc5->stats.reqq_parity_err++; - } - - if (cause & F_DISPQPARERR) { - CH_ALERT(adap, "MC5 dispatch queue parity error\n"); - mc5->stats.dispq_parity_err++; - } - - if (cause & F_ACTRGNFULL) - mc5->stats.active_rgn_full++; - if (cause & F_NFASRCHFAIL) - mc5->stats.nfa_srch_err++; - if (cause & F_UNKNOWNCMD) - mc5->stats.unknown_cmd++; - if (cause & F_DELACTEMPTY) - mc5->stats.del_act_empty++; - if (cause & MC5_INT_FATAL) - t3_fatal_err(adap); - - t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause); -} - -void __devinit t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode) -{ -#define K * 1024 - - static unsigned int tcam_part_size[] = { /* in K 72-bit entries */ - 64 K, 128 K, 256 K, 32 K - }; - -#undef K - - u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG); - - mc5->adapter = adapter; - mc5->mode = (unsigned char)mode; - mc5->part_type = (unsigned char)G_TMTYPE(cfg); - if (cfg & F_TMTYPEHI) - mc5->part_type |= 4; - - mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)]; - if (mode == MC5_MODE_144_BIT) - mc5->tcam_size /= 2; -} diff --git a/trunk/drivers/net/cxgb3/regs.h b/trunk/drivers/net/cxgb3/regs.h deleted file mode 100644 index b56c5f52bcdc..000000000000 --- a/trunk/drivers/net/cxgb3/regs.h +++ /dev/null @@ -1,2195 +0,0 @@ -#define A_SG_CONTROL 0x0 - -#define S_DROPPKT 20 -#define V_DROPPKT(x) ((x) << S_DROPPKT) -#define F_DROPPKT V_DROPPKT(1U) - -#define S_EGRGENCTRL 19 -#define V_EGRGENCTRL(x) ((x) << S_EGRGENCTRL) -#define F_EGRGENCTRL V_EGRGENCTRL(1U) - -#define S_USERSPACESIZE 14 -#define M_USERSPACESIZE 0x1f -#define V_USERSPACESIZE(x) ((x) << S_USERSPACESIZE) - -#define S_HOSTPAGESIZE 11 -#define M_HOSTPAGESIZE 0x7 -#define V_HOSTPAGESIZE(x) ((x) << S_HOSTPAGESIZE) - -#define S_FLMODE 9 -#define V_FLMODE(x) ((x) << S_FLMODE) -#define F_FLMODE V_FLMODE(1U) - -#define S_PKTSHIFT 6 -#define M_PKTSHIFT 0x7 -#define V_PKTSHIFT(x) ((x) << S_PKTSHIFT) - -#define S_ONEINTMULTQ 5 -#define V_ONEINTMULTQ(x) ((x) << S_ONEINTMULTQ) -#define F_ONEINTMULTQ V_ONEINTMULTQ(1U) - -#define S_BIGENDIANINGRESS 2 -#define V_BIGENDIANINGRESS(x) ((x) << S_BIGENDIANINGRESS) -#define F_BIGENDIANINGRESS V_BIGENDIANINGRESS(1U) - -#define S_ISCSICOALESCING 1 -#define V_ISCSICOALESCING(x) ((x) << S_ISCSICOALESCING) -#define F_ISCSICOALESCING V_ISCSICOALESCING(1U) - -#define S_GLOBALENABLE 0 -#define V_GLOBALENABLE(x) ((x) << S_GLOBALENABLE) -#define F_GLOBALENABLE V_GLOBALENABLE(1U) - -#define S_AVOIDCQOVFL 24 -#define V_AVOIDCQOVFL(x) ((x) << S_AVOIDCQOVFL) -#define F_AVOIDCQOVFL V_AVOIDCQOVFL(1U) - -#define S_OPTONEINTMULTQ 23 -#define V_OPTONEINTMULTQ(x) ((x) << S_OPTONEINTMULTQ) -#define F_OPTONEINTMULTQ V_OPTONEINTMULTQ(1U) - -#define S_CQCRDTCTRL 22 -#define V_CQCRDTCTRL(x) ((x) << S_CQCRDTCTRL) -#define F_CQCRDTCTRL V_CQCRDTCTRL(1U) - -#define A_SG_KDOORBELL 0x4 - -#define S_SELEGRCNTX 31 -#define V_SELEGRCNTX(x) ((x) << S_SELEGRCNTX) -#define F_SELEGRCNTX V_SELEGRCNTX(1U) - -#define S_EGRCNTX 0 -#define M_EGRCNTX 0xffff -#define V_EGRCNTX(x) ((x) << S_EGRCNTX) - -#define A_SG_GTS 0x8 - -#define S_RSPQ 29 -#define M_RSPQ 0x7 -#define V_RSPQ(x) ((x) << S_RSPQ) -#define G_RSPQ(x) (((x) >> S_RSPQ) & M_RSPQ) - -#define S_NEWTIMER 16 -#define M_NEWTIMER 0x1fff -#define V_NEWTIMER(x) ((x) << S_NEWTIMER) - -#define S_NEWINDEX 0 -#define M_NEWINDEX 0xffff -#define V_NEWINDEX(x) ((x) << S_NEWINDEX) - -#define A_SG_CONTEXT_CMD 0xc - -#define S_CONTEXT_CMD_OPCODE 28 -#define M_CONTEXT_CMD_OPCODE 0xf -#define V_CONTEXT_CMD_OPCODE(x) ((x) << S_CONTEXT_CMD_OPCODE) - -#define S_CONTEXT_CMD_BUSY 27 -#define V_CONTEXT_CMD_BUSY(x) ((x) << S_CONTEXT_CMD_BUSY) -#define F_CONTEXT_CMD_BUSY V_CONTEXT_CMD_BUSY(1U) - -#define S_CQ_CREDIT 20 - -#define M_CQ_CREDIT 0x7f - -#define V_CQ_CREDIT(x) ((x) << S_CQ_CREDIT) - -#define G_CQ_CREDIT(x) (((x) >> S_CQ_CREDIT) & M_CQ_CREDIT) - -#define S_CQ 19 - -#define V_CQ(x) ((x) << S_CQ) -#define F_CQ V_CQ(1U) - -#define S_RESPONSEQ 18 -#define V_RESPONSEQ(x) ((x) << S_RESPONSEQ) -#define F_RESPONSEQ V_RESPONSEQ(1U) - -#define S_EGRESS 17 -#define V_EGRESS(x) ((x) << S_EGRESS) -#define F_EGRESS V_EGRESS(1U) - -#define S_FREELIST 16 -#define V_FREELIST(x) ((x) << S_FREELIST) -#define F_FREELIST V_FREELIST(1U) - -#define S_CONTEXT 0 -#define M_CONTEXT 0xffff -#define V_CONTEXT(x) ((x) << S_CONTEXT) - -#define G_CONTEXT(x) (((x) >> S_CONTEXT) & M_CONTEXT) - -#define A_SG_CONTEXT_DATA0 0x10 - -#define A_SG_CONTEXT_DATA1 0x14 - -#define A_SG_CONTEXT_DATA2 0x18 - -#define A_SG_CONTEXT_DATA3 0x1c - -#define A_SG_CONTEXT_MASK0 0x20 - -#define A_SG_CONTEXT_MASK1 0x24 - -#define A_SG_CONTEXT_MASK2 0x28 - -#define A_SG_CONTEXT_MASK3 0x2c - -#define A_SG_RSPQ_CREDIT_RETURN 0x30 - -#define S_CREDITS 0 -#define M_CREDITS 0xffff -#define V_CREDITS(x) ((x) << S_CREDITS) - -#define A_SG_DATA_INTR 0x34 - -#define S_ERRINTR 31 -#define V_ERRINTR(x) ((x) << S_ERRINTR) -#define F_ERRINTR V_ERRINTR(1U) - -#define A_SG_HI_DRB_HI_THRSH 0x38 - -#define A_SG_HI_DRB_LO_THRSH 0x3c - -#define A_SG_LO_DRB_HI_THRSH 0x40 - -#define A_SG_LO_DRB_LO_THRSH 0x44 - -#define A_SG_RSPQ_FL_STATUS 0x4c - -#define S_RSPQ0DISABLED 8 - -#define A_SG_EGR_RCQ_DRB_THRSH 0x54 - -#define S_HIRCQDRBTHRSH 16 -#define M_HIRCQDRBTHRSH 0x7ff -#define V_HIRCQDRBTHRSH(x) ((x) << S_HIRCQDRBTHRSH) - -#define S_LORCQDRBTHRSH 0 -#define M_LORCQDRBTHRSH 0x7ff -#define V_LORCQDRBTHRSH(x) ((x) << S_LORCQDRBTHRSH) - -#define A_SG_EGR_CNTX_BADDR 0x58 - -#define A_SG_INT_CAUSE 0x5c - -#define S_RSPQDISABLED 3 -#define V_RSPQDISABLED(x) ((x) << S_RSPQDISABLED) -#define F_RSPQDISABLED V_RSPQDISABLED(1U) - -#define S_RSPQCREDITOVERFOW 2 -#define V_RSPQCREDITOVERFOW(x) ((x) << S_RSPQCREDITOVERFOW) -#define F_RSPQCREDITOVERFOW V_RSPQCREDITOVERFOW(1U) - -#define A_SG_INT_ENABLE 0x60 - -#define A_SG_CMDQ_CREDIT_TH 0x64 - -#define S_TIMEOUT 8 -#define M_TIMEOUT 0xffffff -#define V_TIMEOUT(x) ((x) << S_TIMEOUT) - -#define S_THRESHOLD 0 -#define M_THRESHOLD 0xff -#define V_THRESHOLD(x) ((x) << S_THRESHOLD) - -#define A_SG_TIMER_TICK 0x68 - -#define A_SG_CQ_CONTEXT_BADDR 0x6c - -#define A_SG_OCO_BASE 0x70 - -#define S_BASE1 16 -#define M_BASE1 0xffff -#define V_BASE1(x) ((x) << S_BASE1) - -#define A_SG_DRB_PRI_THRESH 0x74 - -#define A_PCIX_INT_ENABLE 0x80 - -#define S_MSIXPARERR 22 -#define M_MSIXPARERR 0x7 - -#define V_MSIXPARERR(x) ((x) << S_MSIXPARERR) - -#define S_CFPARERR 18 -#define M_CFPARERR 0xf - -#define V_CFPARERR(x) ((x) << S_CFPARERR) - -#define S_RFPARERR 14 -#define M_RFPARERR 0xf - -#define V_RFPARERR(x) ((x) << S_RFPARERR) - -#define S_WFPARERR 12 -#define M_WFPARERR 0x3 - -#define V_WFPARERR(x) ((x) << S_WFPARERR) - -#define S_PIOPARERR 11 -#define V_PIOPARERR(x) ((x) << S_PIOPARERR) -#define F_PIOPARERR V_PIOPARERR(1U) - -#define S_DETUNCECCERR 10 -#define V_DETUNCECCERR(x) ((x) << S_DETUNCECCERR) -#define F_DETUNCECCERR V_DETUNCECCERR(1U) - -#define S_DETCORECCERR 9 -#define V_DETCORECCERR(x) ((x) << S_DETCORECCERR) -#define F_DETCORECCERR V_DETCORECCERR(1U) - -#define S_RCVSPLCMPERR 8 -#define V_RCVSPLCMPERR(x) ((x) << S_RCVSPLCMPERR) -#define F_RCVSPLCMPERR V_RCVSPLCMPERR(1U) - -#define S_UNXSPLCMP 7 -#define V_UNXSPLCMP(x) ((x) << S_UNXSPLCMP) -#define F_UNXSPLCMP V_UNXSPLCMP(1U) - -#define S_SPLCMPDIS 6 -#define V_SPLCMPDIS(x) ((x) << S_SPLCMPDIS) -#define F_SPLCMPDIS V_SPLCMPDIS(1U) - -#define S_DETPARERR 5 -#define V_DETPARERR(x) ((x) << S_DETPARERR) -#define F_DETPARERR V_DETPARERR(1U) - -#define S_SIGSYSERR 4 -#define V_SIGSYSERR(x) ((x) << S_SIGSYSERR) -#define F_SIGSYSERR V_SIGSYSERR(1U) - -#define S_RCVMSTABT 3 -#define V_RCVMSTABT(x) ((x) << S_RCVMSTABT) -#define F_RCVMSTABT V_RCVMSTABT(1U) - -#define S_RCVTARABT 2 -#define V_RCVTARABT(x) ((x) << S_RCVTARABT) -#define F_RCVTARABT V_RCVTARABT(1U) - -#define S_SIGTARABT 1 -#define V_SIGTARABT(x) ((x) << S_SIGTARABT) -#define F_SIGTARABT V_SIGTARABT(1U) - -#define S_MSTDETPARERR 0 -#define V_MSTDETPARERR(x) ((x) << S_MSTDETPARERR) -#define F_MSTDETPARERR V_MSTDETPARERR(1U) - -#define A_PCIX_INT_CAUSE 0x84 - -#define A_PCIX_CFG 0x88 - -#define S_CLIDECEN 18 -#define V_CLIDECEN(x) ((x) << S_CLIDECEN) -#define F_CLIDECEN V_CLIDECEN(1U) - -#define A_PCIX_MODE 0x8c - -#define S_PCLKRANGE 6 -#define M_PCLKRANGE 0x3 -#define V_PCLKRANGE(x) ((x) << S_PCLKRANGE) -#define G_PCLKRANGE(x) (((x) >> S_PCLKRANGE) & M_PCLKRANGE) - -#define S_PCIXINITPAT 2 -#define M_PCIXINITPAT 0xf -#define V_PCIXINITPAT(x) ((x) << S_PCIXINITPAT) -#define G_PCIXINITPAT(x) (((x) >> S_PCIXINITPAT) & M_PCIXINITPAT) - -#define S_64BIT 0 -#define V_64BIT(x) ((x) << S_64BIT) -#define F_64BIT V_64BIT(1U) - -#define A_PCIE_INT_ENABLE 0x80 - -#define S_BISTERR 15 -#define M_BISTERR 0xff - -#define V_BISTERR(x) ((x) << S_BISTERR) - -#define S_PCIE_MSIXPARERR 12 -#define M_PCIE_MSIXPARERR 0x7 - -#define V_PCIE_MSIXPARERR(x) ((x) << S_PCIE_MSIXPARERR) - -#define S_PCIE_CFPARERR 11 -#define V_PCIE_CFPARERR(x) ((x) << S_PCIE_CFPARERR) -#define F_PCIE_CFPARERR V_PCIE_CFPARERR(1U) - -#define S_PCIE_RFPARERR 10 -#define V_PCIE_RFPARERR(x) ((x) << S_PCIE_RFPARERR) -#define F_PCIE_RFPARERR V_PCIE_RFPARERR(1U) - -#define S_PCIE_WFPARERR 9 -#define V_PCIE_WFPARERR(x) ((x) << S_PCIE_WFPARERR) -#define F_PCIE_WFPARERR V_PCIE_WFPARERR(1U) - -#define S_PCIE_PIOPARERR 8 -#define V_PCIE_PIOPARERR(x) ((x) << S_PCIE_PIOPARERR) -#define F_PCIE_PIOPARERR V_PCIE_PIOPARERR(1U) - -#define S_UNXSPLCPLERRC 7 -#define V_UNXSPLCPLERRC(x) ((x) << S_UNXSPLCPLERRC) -#define F_UNXSPLCPLERRC V_UNXSPLCPLERRC(1U) - -#define S_UNXSPLCPLERRR 6 -#define V_UNXSPLCPLERRR(x) ((x) << S_UNXSPLCPLERRR) -#define F_UNXSPLCPLERRR V_UNXSPLCPLERRR(1U) - -#define S_PEXERR 0 -#define V_PEXERR(x) ((x) << S_PEXERR) -#define F_PEXERR V_PEXERR(1U) - -#define A_PCIE_INT_CAUSE 0x84 - -#define A_PCIE_CFG 0x88 - -#define S_PCIE_CLIDECEN 16 -#define V_PCIE_CLIDECEN(x) ((x) << S_PCIE_CLIDECEN) -#define F_PCIE_CLIDECEN V_PCIE_CLIDECEN(1U) - -#define S_CRSTWRMMODE 0 -#define V_CRSTWRMMODE(x) ((x) << S_CRSTWRMMODE) -#define F_CRSTWRMMODE V_CRSTWRMMODE(1U) - -#define A_PCIE_MODE 0x8c - -#define S_NUMFSTTRNSEQRX 10 -#define M_NUMFSTTRNSEQRX 0xff -#define V_NUMFSTTRNSEQRX(x) ((x) << S_NUMFSTTRNSEQRX) -#define G_NUMFSTTRNSEQRX(x) (((x) >> S_NUMFSTTRNSEQRX) & M_NUMFSTTRNSEQRX) - -#define A_PCIE_PEX_CTRL0 0x98 - -#define S_NUMFSTTRNSEQ 22 -#define M_NUMFSTTRNSEQ 0xff -#define V_NUMFSTTRNSEQ(x) ((x) << S_NUMFSTTRNSEQ) -#define G_NUMFSTTRNSEQ(x) (((x) >> S_NUMFSTTRNSEQ) & M_NUMFSTTRNSEQ) - -#define S_REPLAYLMT 2 -#define M_REPLAYLMT 0xfffff - -#define V_REPLAYLMT(x) ((x) << S_REPLAYLMT) - -#define A_PCIE_PEX_CTRL1 0x9c - -#define S_T3A_ACKLAT 0 -#define M_T3A_ACKLAT 0x7ff - -#define V_T3A_ACKLAT(x) ((x) << S_T3A_ACKLAT) - -#define S_ACKLAT 0 -#define M_ACKLAT 0x1fff - -#define V_ACKLAT(x) ((x) << S_ACKLAT) - -#define A_PCIE_PEX_ERR 0xa4 - -#define A_T3DBG_GPIO_EN 0xd0 - -#define S_GPIO11_OEN 27 -#define V_GPIO11_OEN(x) ((x) << S_GPIO11_OEN) -#define F_GPIO11_OEN V_GPIO11_OEN(1U) - -#define S_GPIO10_OEN 26 -#define V_GPIO10_OEN(x) ((x) << S_GPIO10_OEN) -#define F_GPIO10_OEN V_GPIO10_OEN(1U) - -#define S_GPIO7_OEN 23 -#define V_GPIO7_OEN(x) ((x) << S_GPIO7_OEN) -#define F_GPIO7_OEN V_GPIO7_OEN(1U) - -#define S_GPIO6_OEN 22 -#define V_GPIO6_OEN(x) ((x) << S_GPIO6_OEN) -#define F_GPIO6_OEN V_GPIO6_OEN(1U) - -#define S_GPIO5_OEN 21 -#define V_GPIO5_OEN(x) ((x) << S_GPIO5_OEN) -#define F_GPIO5_OEN V_GPIO5_OEN(1U) - -#define S_GPIO4_OEN 20 -#define V_GPIO4_OEN(x) ((x) << S_GPIO4_OEN) -#define F_GPIO4_OEN V_GPIO4_OEN(1U) - -#define S_GPIO2_OEN 18 -#define V_GPIO2_OEN(x) ((x) << S_GPIO2_OEN) -#define F_GPIO2_OEN V_GPIO2_OEN(1U) - -#define S_GPIO1_OEN 17 -#define V_GPIO1_OEN(x) ((x) << S_GPIO1_OEN) -#define F_GPIO1_OEN V_GPIO1_OEN(1U) - -#define S_GPIO0_OEN 16 -#define V_GPIO0_OEN(x) ((x) << S_GPIO0_OEN) -#define F_GPIO0_OEN V_GPIO0_OEN(1U) - -#define S_GPIO10_OUT_VAL 10 -#define V_GPIO10_OUT_VAL(x) ((x) << S_GPIO10_OUT_VAL) -#define F_GPIO10_OUT_VAL V_GPIO10_OUT_VAL(1U) - -#define S_GPIO7_OUT_VAL 7 -#define V_GPIO7_OUT_VAL(x) ((x) << S_GPIO7_OUT_VAL) -#define F_GPIO7_OUT_VAL V_GPIO7_OUT_VAL(1U) - -#define S_GPIO6_OUT_VAL 6 -#define V_GPIO6_OUT_VAL(x) ((x) << S_GPIO6_OUT_VAL) -#define F_GPIO6_OUT_VAL V_GPIO6_OUT_VAL(1U) - -#define S_GPIO5_OUT_VAL 5 -#define V_GPIO5_OUT_VAL(x) ((x) << S_GPIO5_OUT_VAL) -#define F_GPIO5_OUT_VAL V_GPIO5_OUT_VAL(1U) - -#define S_GPIO4_OUT_VAL 4 -#define V_GPIO4_OUT_VAL(x) ((x) << S_GPIO4_OUT_VAL) -#define F_GPIO4_OUT_VAL V_GPIO4_OUT_VAL(1U) - -#define S_GPIO2_OUT_VAL 2 -#define V_GPIO2_OUT_VAL(x) ((x) << S_GPIO2_OUT_VAL) -#define F_GPIO2_OUT_VAL V_GPIO2_OUT_VAL(1U) - -#define S_GPIO1_OUT_VAL 1 -#define V_GPIO1_OUT_VAL(x) ((x) << S_GPIO1_OUT_VAL) -#define F_GPIO1_OUT_VAL V_GPIO1_OUT_VAL(1U) - -#define S_GPIO0_OUT_VAL 0 -#define V_GPIO0_OUT_VAL(x) ((x) << S_GPIO0_OUT_VAL) -#define F_GPIO0_OUT_VAL V_GPIO0_OUT_VAL(1U) - -#define A_T3DBG_INT_ENABLE 0xd8 - -#define S_GPIO11 11 -#define V_GPIO11(x) ((x) << S_GPIO11) -#define F_GPIO11 V_GPIO11(1U) - -#define S_GPIO10 10 -#define V_GPIO10(x) ((x) << S_GPIO10) -#define F_GPIO10 V_GPIO10(1U) - -#define S_GPIO7 7 -#define V_GPIO7(x) ((x) << S_GPIO7) -#define F_GPIO7 V_GPIO7(1U) - -#define S_GPIO6 6 -#define V_GPIO6(x) ((x) << S_GPIO6) -#define F_GPIO6 V_GPIO6(1U) - -#define S_GPIO5 5 -#define V_GPIO5(x) ((x) << S_GPIO5) -#define F_GPIO5 V_GPIO5(1U) - -#define S_GPIO4 4 -#define V_GPIO4(x) ((x) << S_GPIO4) -#define F_GPIO4 V_GPIO4(1U) - -#define S_GPIO3 3 -#define V_GPIO3(x) ((x) << S_GPIO3) -#define F_GPIO3 V_GPIO3(1U) - -#define S_GPIO2 2 -#define V_GPIO2(x) ((x) << S_GPIO2) -#define F_GPIO2 V_GPIO2(1U) - -#define S_GPIO1 1 -#define V_GPIO1(x) ((x) << S_GPIO1) -#define F_GPIO1 V_GPIO1(1U) - -#define S_GPIO0 0 -#define V_GPIO0(x) ((x) << S_GPIO0) -#define F_GPIO0 V_GPIO0(1U) - -#define A_T3DBG_INT_CAUSE 0xdc - -#define A_T3DBG_GPIO_ACT_LOW 0xf0 - -#define MC7_PMRX_BASE_ADDR 0x100 - -#define A_MC7_CFG 0x100 - -#define S_IFEN 13 -#define V_IFEN(x) ((x) << S_IFEN) -#define F_IFEN V_IFEN(1U) - -#define S_TERM150 11 -#define V_TERM150(x) ((x) << S_TERM150) -#define F_TERM150 V_TERM150(1U) - -#define S_SLOW 10 -#define V_SLOW(x) ((x) << S_SLOW) -#define F_SLOW V_SLOW(1U) - -#define S_WIDTH 8 -#define M_WIDTH 0x3 -#define V_WIDTH(x) ((x) << S_WIDTH) -#define G_WIDTH(x) (((x) >> S_WIDTH) & M_WIDTH) - -#define S_BKS 6 -#define V_BKS(x) ((x) << S_BKS) -#define F_BKS V_BKS(1U) - -#define S_ORG 5 -#define V_ORG(x) ((x) << S_ORG) -#define F_ORG V_ORG(1U) - -#define S_DEN 2 -#define M_DEN 0x7 -#define V_DEN(x) ((x) << S_DEN) -#define G_DEN(x) (((x) >> S_DEN) & M_DEN) - -#define S_RDY 1 -#define V_RDY(x) ((x) << S_RDY) -#define F_RDY V_RDY(1U) - -#define S_CLKEN 0 -#define V_CLKEN(x) ((x) << S_CLKEN) -#define F_CLKEN V_CLKEN(1U) - -#define A_MC7_MODE 0x104 - -#define S_BUSY 31 -#define V_BUSY(x) ((x) << S_BUSY) -#define F_BUSY V_BUSY(1U) - -#define S_BUSY 31 -#define V_BUSY(x) ((x) << S_BUSY) -#define F_BUSY V_BUSY(1U) - -#define A_MC7_EXT_MODE1 0x108 - -#define A_MC7_EXT_MODE2 0x10c - -#define A_MC7_EXT_MODE3 0x110 - -#define A_MC7_PRE 0x114 - -#define A_MC7_REF 0x118 - -#define S_PREREFDIV 1 -#define M_PREREFDIV 0x3fff -#define V_PREREFDIV(x) ((x) << S_PREREFDIV) - -#define S_PERREFEN 0 -#define V_PERREFEN(x) ((x) << S_PERREFEN) -#define F_PERREFEN V_PERREFEN(1U) - -#define A_MC7_DLL 0x11c - -#define S_DLLENB 1 -#define V_DLLENB(x) ((x) << S_DLLENB) -#define F_DLLENB V_DLLENB(1U) - -#define S_DLLRST 0 -#define V_DLLRST(x) ((x) << S_DLLRST) -#define F_DLLRST V_DLLRST(1U) - -#define A_MC7_PARM 0x120 - -#define S_ACTTOPREDLY 26 -#define M_ACTTOPREDLY 0xf -#define V_ACTTOPREDLY(x) ((x) << S_ACTTOPREDLY) - -#define S_ACTTORDWRDLY 23 -#define M_ACTTORDWRDLY 0x7 -#define V_ACTTORDWRDLY(x) ((x) << S_ACTTORDWRDLY) - -#define S_PRECYC 20 -#define M_PRECYC 0x7 -#define V_PRECYC(x) ((x) << S_PRECYC) - -#define S_REFCYC 13 -#define M_REFCYC 0x7f -#define V_REFCYC(x) ((x) << S_REFCYC) - -#define S_BKCYC 8 -#define M_BKCYC 0x1f -#define V_BKCYC(x) ((x) << S_BKCYC) - -#define S_WRTORDDLY 4 -#define M_WRTORDDLY 0xf -#define V_WRTORDDLY(x) ((x) << S_WRTORDDLY) - -#define S_RDTOWRDLY 0 -#define M_RDTOWRDLY 0xf -#define V_RDTOWRDLY(x) ((x) << S_RDTOWRDLY) - -#define A_MC7_CAL 0x128 - -#define S_BUSY 31 -#define V_BUSY(x) ((x) << S_BUSY) -#define F_BUSY V_BUSY(1U) - -#define S_BUSY 31 -#define V_BUSY(x) ((x) << S_BUSY) -#define F_BUSY V_BUSY(1U) - -#define S_CAL_FAULT 30 -#define V_CAL_FAULT(x) ((x) << S_CAL_FAULT) -#define F_CAL_FAULT V_CAL_FAULT(1U) - -#define S_SGL_CAL_EN 20 -#define V_SGL_CAL_EN(x) ((x) << S_SGL_CAL_EN) -#define F_SGL_CAL_EN V_SGL_CAL_EN(1U) - -#define A_MC7_ERR_ADDR 0x12c - -#define A_MC7_ECC 0x130 - -#define S_ECCCHKEN 1 -#define V_ECCCHKEN(x) ((x) << S_ECCCHKEN) -#define F_ECCCHKEN V_ECCCHKEN(1U) - -#define S_ECCGENEN 0 -#define V_ECCGENEN(x) ((x) << S_ECCGENEN) -#define F_ECCGENEN V_ECCGENEN(1U) - -#define A_MC7_CE_ADDR 0x134 - -#define A_MC7_CE_DATA0 0x138 - -#define A_MC7_CE_DATA1 0x13c - -#define A_MC7_CE_DATA2 0x140 - -#define S_DATA 0 -#define M_DATA 0xff - -#define G_DATA(x) (((x) >> S_DATA) & M_DATA) - -#define A_MC7_UE_ADDR 0x144 - -#define A_MC7_UE_DATA0 0x148 - -#define A_MC7_UE_DATA1 0x14c - -#define A_MC7_UE_DATA2 0x150 - -#define A_MC7_BD_ADDR 0x154 - -#define S_ADDR 3 - -#define M_ADDR 0x1fffffff - -#define A_MC7_BD_DATA0 0x158 - -#define A_MC7_BD_DATA1 0x15c - -#define A_MC7_BD_OP 0x164 - -#define S_OP 0 - -#define V_OP(x) ((x) << S_OP) -#define F_OP V_OP(1U) - -#define F_OP V_OP(1U) -#define A_SF_OP 0x6dc - -#define A_MC7_BIST_ADDR_BEG 0x168 - -#define A_MC7_BIST_ADDR_END 0x16c - -#define A_MC7_BIST_DATA 0x170 - -#define A_MC7_BIST_OP 0x174 - -#define S_CONT 3 -#define V_CONT(x) ((x) << S_CONT) -#define F_CONT V_CONT(1U) - -#define F_CONT V_CONT(1U) - -#define A_MC7_INT_ENABLE 0x178 - -#define S_AE 17 -#define V_AE(x) ((x) << S_AE) -#define F_AE V_AE(1U) - -#define S_PE 2 -#define M_PE 0x7fff - -#define V_PE(x) ((x) << S_PE) - -#define G_PE(x) (((x) >> S_PE) & M_PE) - -#define S_UE 1 -#define V_UE(x) ((x) << S_UE) -#define F_UE V_UE(1U) - -#define S_CE 0 -#define V_CE(x) ((x) << S_CE) -#define F_CE V_CE(1U) - -#define A_MC7_INT_CAUSE 0x17c - -#define MC7_PMTX_BASE_ADDR 0x180 - -#define MC7_CM_BASE_ADDR 0x200 - -#define A_CIM_BOOT_CFG 0x280 - -#define S_BOOTADDR 2 -#define M_BOOTADDR 0x3fffffff -#define V_BOOTADDR(x) ((x) << S_BOOTADDR) - -#define A_CIM_SDRAM_BASE_ADDR 0x28c - -#define A_CIM_SDRAM_ADDR_SIZE 0x290 - -#define A_CIM_HOST_INT_ENABLE 0x298 - -#define A_CIM_HOST_INT_CAUSE 0x29c - -#define S_BLKWRPLINT 12 -#define V_BLKWRPLINT(x) ((x) << S_BLKWRPLINT) -#define F_BLKWRPLINT V_BLKWRPLINT(1U) - -#define S_BLKRDPLINT 11 -#define V_BLKRDPLINT(x) ((x) << S_BLKRDPLINT) -#define F_BLKRDPLINT V_BLKRDPLINT(1U) - -#define S_BLKWRCTLINT 10 -#define V_BLKWRCTLINT(x) ((x) << S_BLKWRCTLINT) -#define F_BLKWRCTLINT V_BLKWRCTLINT(1U) - -#define S_BLKRDCTLINT 9 -#define V_BLKRDCTLINT(x) ((x) << S_BLKRDCTLINT) -#define F_BLKRDCTLINT V_BLKRDCTLINT(1U) - -#define S_BLKWRFLASHINT 8 -#define V_BLKWRFLASHINT(x) ((x) << S_BLKWRFLASHINT) -#define F_BLKWRFLASHINT V_BLKWRFLASHINT(1U) - -#define S_BLKRDFLASHINT 7 -#define V_BLKRDFLASHINT(x) ((x) << S_BLKRDFLASHINT) -#define F_BLKRDFLASHINT V_BLKRDFLASHINT(1U) - -#define S_SGLWRFLASHINT 6 -#define V_SGLWRFLASHINT(x) ((x) << S_SGLWRFLASHINT) -#define F_SGLWRFLASHINT V_SGLWRFLASHINT(1U) - -#define S_WRBLKFLASHINT 5 -#define V_WRBLKFLASHINT(x) ((x) << S_WRBLKFLASHINT) -#define F_WRBLKFLASHINT V_WRBLKFLASHINT(1U) - -#define S_BLKWRBOOTINT 4 -#define V_BLKWRBOOTINT(x) ((x) << S_BLKWRBOOTINT) -#define F_BLKWRBOOTINT V_BLKWRBOOTINT(1U) - -#define S_FLASHRANGEINT 2 -#define V_FLASHRANGEINT(x) ((x) << S_FLASHRANGEINT) -#define F_FLASHRANGEINT V_FLASHRANGEINT(1U) - -#define S_SDRAMRANGEINT 1 -#define V_SDRAMRANGEINT(x) ((x) << S_SDRAMRANGEINT) -#define F_SDRAMRANGEINT V_SDRAMRANGEINT(1U) - -#define S_RSVDSPACEINT 0 -#define V_RSVDSPACEINT(x) ((x) << S_RSVDSPACEINT) -#define F_RSVDSPACEINT V_RSVDSPACEINT(1U) - -#define A_CIM_HOST_ACC_CTRL 0x2b0 - -#define S_HOSTBUSY 17 -#define V_HOSTBUSY(x) ((x) << S_HOSTBUSY) -#define F_HOSTBUSY V_HOSTBUSY(1U) - -#define A_CIM_HOST_ACC_DATA 0x2b4 - -#define A_TP_IN_CONFIG 0x300 - -#define S_NICMODE 14 -#define V_NICMODE(x) ((x) << S_NICMODE) -#define F_NICMODE V_NICMODE(1U) - -#define F_NICMODE V_NICMODE(1U) - -#define S_IPV6ENABLE 15 -#define V_IPV6ENABLE(x) ((x) << S_IPV6ENABLE) -#define F_IPV6ENABLE V_IPV6ENABLE(1U) - -#define A_TP_OUT_CONFIG 0x304 - -#define S_VLANEXTRACTIONENABLE 12 - -#define A_TP_GLOBAL_CONFIG 0x308 - -#define S_TXPACINGENABLE 24 -#define V_TXPACINGENABLE(x) ((x) << S_TXPACINGENABLE) -#define F_TXPACINGENABLE V_TXPACINGENABLE(1U) - -#define S_PATHMTU 15 -#define V_PATHMTU(x) ((x) << S_PATHMTU) -#define F_PATHMTU V_PATHMTU(1U) - -#define S_IPCHECKSUMOFFLOAD 13 -#define V_IPCHECKSUMOFFLOAD(x) ((x) << S_IPCHECKSUMOFFLOAD) -#define F_IPCHECKSUMOFFLOAD V_IPCHECKSUMOFFLOAD(1U) - -#define S_UDPCHECKSUMOFFLOAD 12 -#define V_UDPCHECKSUMOFFLOAD(x) ((x) << S_UDPCHECKSUMOFFLOAD) -#define F_UDPCHECKSUMOFFLOAD V_UDPCHECKSUMOFFLOAD(1U) - -#define S_TCPCHECKSUMOFFLOAD 11 -#define V_TCPCHECKSUMOFFLOAD(x) ((x) << S_TCPCHECKSUMOFFLOAD) -#define F_TCPCHECKSUMOFFLOAD V_TCPCHECKSUMOFFLOAD(1U) - -#define S_IPTTL 0 -#define M_IPTTL 0xff -#define V_IPTTL(x) ((x) << S_IPTTL) - -#define A_TP_CMM_MM_BASE 0x314 - -#define A_TP_CMM_TIMER_BASE 0x318 - -#define S_CMTIMERMAXNUM 28 -#define M_CMTIMERMAXNUM 0x3 -#define V_CMTIMERMAXNUM(x) ((x) << S_CMTIMERMAXNUM) - -#define A_TP_PMM_SIZE 0x31c - -#define A_TP_PMM_TX_BASE 0x320 - -#define A_TP_PMM_RX_BASE 0x328 - -#define A_TP_PMM_RX_PAGE_SIZE 0x32c - -#define A_TP_PMM_RX_MAX_PAGE 0x330 - -#define A_TP_PMM_TX_PAGE_SIZE 0x334 - -#define A_TP_PMM_TX_MAX_PAGE 0x338 - -#define A_TP_TCP_OPTIONS 0x340 - -#define S_MTUDEFAULT 16 -#define M_MTUDEFAULT 0xffff -#define V_MTUDEFAULT(x) ((x) << S_MTUDEFAULT) - -#define S_MTUENABLE 10 -#define V_MTUENABLE(x) ((x) << S_MTUENABLE) -#define F_MTUENABLE V_MTUENABLE(1U) - -#define S_SACKRX 8 -#define V_SACKRX(x) ((x) << S_SACKRX) -#define F_SACKRX V_SACKRX(1U) - -#define S_SACKMODE 4 - -#define M_SACKMODE 0x3 - -#define V_SACKMODE(x) ((x) << S_SACKMODE) - -#define S_WINDOWSCALEMODE 2 -#define M_WINDOWSCALEMODE 0x3 -#define V_WINDOWSCALEMODE(x) ((x) << S_WINDOWSCALEMODE) - -#define S_TIMESTAMPSMODE 0 - -#define M_TIMESTAMPSMODE 0x3 - -#define V_TIMESTAMPSMODE(x) ((x) << S_TIMESTAMPSMODE) - -#define A_TP_DACK_CONFIG 0x344 - -#define S_AUTOSTATE3 30 -#define M_AUTOSTATE3 0x3 -#define V_AUTOSTATE3(x) ((x) << S_AUTOSTATE3) - -#define S_AUTOSTATE2 28 -#define M_AUTOSTATE2 0x3 -#define V_AUTOSTATE2(x) ((x) << S_AUTOSTATE2) - -#define S_AUTOSTATE1 26 -#define M_AUTOSTATE1 0x3 -#define V_AUTOSTATE1(x) ((x) << S_AUTOSTATE1) - -#define S_BYTETHRESHOLD 5 -#define M_BYTETHRESHOLD 0xfffff -#define V_BYTETHRESHOLD(x) ((x) << S_BYTETHRESHOLD) - -#define S_MSSTHRESHOLD 3 -#define M_MSSTHRESHOLD 0x3 -#define V_MSSTHRESHOLD(x) ((x) << S_MSSTHRESHOLD) - -#define S_AUTOCAREFUL 2 -#define V_AUTOCAREFUL(x) ((x) << S_AUTOCAREFUL) -#define F_AUTOCAREFUL V_AUTOCAREFUL(1U) - -#define S_AUTOENABLE 1 -#define V_AUTOENABLE(x) ((x) << S_AUTOENABLE) -#define F_AUTOENABLE V_AUTOENABLE(1U) - -#define S_DACK_MODE 0 -#define V_DACK_MODE(x) ((x) << S_DACK_MODE) -#define F_DACK_MODE V_DACK_MODE(1U) - -#define A_TP_PC_CONFIG 0x348 - -#define S_TXTOSQUEUEMAPMODE 26 -#define V_TXTOSQUEUEMAPMODE(x) ((x) << S_TXTOSQUEUEMAPMODE) -#define F_TXTOSQUEUEMAPMODE V_TXTOSQUEUEMAPMODE(1U) - -#define S_ENABLEEPCMDAFULL 23 -#define V_ENABLEEPCMDAFULL(x) ((x) << S_ENABLEEPCMDAFULL) -#define F_ENABLEEPCMDAFULL V_ENABLEEPCMDAFULL(1U) - -#define S_MODULATEUNIONMODE 22 -#define V_MODULATEUNIONMODE(x) ((x) << S_MODULATEUNIONMODE) -#define F_MODULATEUNIONMODE V_MODULATEUNIONMODE(1U) - -#define S_TXDEFERENABLE 20 -#define V_TXDEFERENABLE(x) ((x) << S_TXDEFERENABLE) -#define F_TXDEFERENABLE V_TXDEFERENABLE(1U) - -#define S_RXCONGESTIONMODE 19 -#define V_RXCONGESTIONMODE(x) ((x) << S_RXCONGESTIONMODE) -#define F_RXCONGESTIONMODE V_RXCONGESTIONMODE(1U) - -#define S_HEARBEATDACK 16 -#define V_HEARBEATDACK(x) ((x) << S_HEARBEATDACK) -#define F_HEARBEATDACK V_HEARBEATDACK(1U) - -#define S_TXCONGESTIONMODE 15 -#define V_TXCONGESTIONMODE(x) ((x) << S_TXCONGESTIONMODE) -#define F_TXCONGESTIONMODE V_TXCONGESTIONMODE(1U) - -#define S_ENABLEOCSPIFULL 30 -#define V_ENABLEOCSPIFULL(x) ((x) << S_ENABLEOCSPIFULL) -#define F_ENABLEOCSPIFULL V_ENABLEOCSPIFULL(1U) - -#define S_LOCKTID 28 -#define V_LOCKTID(x) ((x) << S_LOCKTID) -#define F_LOCKTID V_LOCKTID(1U) - -#define A_TP_PC_CONFIG2 0x34c - -#define S_CHDRAFULL 4 -#define V_CHDRAFULL(x) ((x) << S_CHDRAFULL) -#define F_CHDRAFULL V_CHDRAFULL(1U) - -#define A_TP_TCP_BACKOFF_REG0 0x350 - -#define A_TP_TCP_BACKOFF_REG1 0x354 - -#define A_TP_TCP_BACKOFF_REG2 0x358 - -#define A_TP_TCP_BACKOFF_REG3 0x35c - -#define A_TP_PARA_REG2 0x368 - -#define S_MAXRXDATA 16 -#define M_MAXRXDATA 0xffff -#define V_MAXRXDATA(x) ((x) << S_MAXRXDATA) - -#define S_RXCOALESCESIZE 0 -#define M_RXCOALESCESIZE 0xffff -#define V_RXCOALESCESIZE(x) ((x) << S_RXCOALESCESIZE) - -#define A_TP_PARA_REG3 0x36c - -#define S_TXDATAACKIDX 16 -#define M_TXDATAACKIDX 0xf - -#define V_TXDATAACKIDX(x) ((x) << S_TXDATAACKIDX) - -#define S_TXPACEAUTOSTRICT 10 -#define V_TXPACEAUTOSTRICT(x) ((x) << S_TXPACEAUTOSTRICT) -#define F_TXPACEAUTOSTRICT V_TXPACEAUTOSTRICT(1U) - -#define S_TXPACEFIXED 9 -#define V_TXPACEFIXED(x) ((x) << S_TXPACEFIXED) -#define F_TXPACEFIXED V_TXPACEFIXED(1U) - -#define S_TXPACEAUTO 8 -#define V_TXPACEAUTO(x) ((x) << S_TXPACEAUTO) -#define F_TXPACEAUTO V_TXPACEAUTO(1U) - -#define S_RXCOALESCEENABLE 1 -#define V_RXCOALESCEENABLE(x) ((x) << S_RXCOALESCEENABLE) -#define F_RXCOALESCEENABLE V_RXCOALESCEENABLE(1U) - -#define S_RXCOALESCEPSHEN 0 -#define V_RXCOALESCEPSHEN(x) ((x) << S_RXCOALESCEPSHEN) -#define F_RXCOALESCEPSHEN V_RXCOALESCEPSHEN(1U) - -#define A_TP_PARA_REG4 0x370 - -#define A_TP_PARA_REG6 0x378 - -#define S_T3A_ENABLEESND 13 -#define V_T3A_ENABLEESND(x) ((x) << S_T3A_ENABLEESND) -#define F_T3A_ENABLEESND V_T3A_ENABLEESND(1U) - -#define S_ENABLEESND 11 -#define V_ENABLEESND(x) ((x) << S_ENABLEESND) -#define F_ENABLEESND V_ENABLEESND(1U) - -#define A_TP_PARA_REG7 0x37c - -#define S_PMMAXXFERLEN1 16 -#define M_PMMAXXFERLEN1 0xffff -#define V_PMMAXXFERLEN1(x) ((x) << S_PMMAXXFERLEN1) - -#define S_PMMAXXFERLEN0 0 -#define M_PMMAXXFERLEN0 0xffff -#define V_PMMAXXFERLEN0(x) ((x) << S_PMMAXXFERLEN0) - -#define A_TP_TIMER_RESOLUTION 0x390 - -#define S_TIMERRESOLUTION 16 -#define M_TIMERRESOLUTION 0xff -#define V_TIMERRESOLUTION(x) ((x) << S_TIMERRESOLUTION) - -#define S_TIMESTAMPRESOLUTION 8 -#define M_TIMESTAMPRESOLUTION 0xff -#define V_TIMESTAMPRESOLUTION(x) ((x) << S_TIMESTAMPRESOLUTION) - -#define S_DELAYEDACKRESOLUTION 0 -#define M_DELAYEDACKRESOLUTION 0xff -#define V_DELAYEDACKRESOLUTION(x) ((x) << S_DELAYEDACKRESOLUTION) - -#define A_TP_MSL 0x394 - -#define A_TP_RXT_MIN 0x398 - -#define A_TP_RXT_MAX 0x39c - -#define A_TP_PERS_MIN 0x3a0 - -#define A_TP_PERS_MAX 0x3a4 - -#define A_TP_KEEP_IDLE 0x3a8 - -#define A_TP_KEEP_INTVL 0x3ac - -#define A_TP_INIT_SRTT 0x3b0 - -#define A_TP_DACK_TIMER 0x3b4 - -#define A_TP_FINWAIT2_TIMER 0x3b8 - -#define A_TP_SHIFT_CNT 0x3c0 - -#define S_SYNSHIFTMAX 24 - -#define M_SYNSHIFTMAX 0xff - -#define V_SYNSHIFTMAX(x) ((x) << S_SYNSHIFTMAX) - -#define S_RXTSHIFTMAXR1 20 - -#define M_RXTSHIFTMAXR1 0xf - -#define V_RXTSHIFTMAXR1(x) ((x) << S_RXTSHIFTMAXR1) - -#define S_RXTSHIFTMAXR2 16 - -#define M_RXTSHIFTMAXR2 0xf - -#define V_RXTSHIFTMAXR2(x) ((x) << S_RXTSHIFTMAXR2) - -#define S_PERSHIFTBACKOFFMAX 12 -#define M_PERSHIFTBACKOFFMAX 0xf -#define V_PERSHIFTBACKOFFMAX(x) ((x) << S_PERSHIFTBACKOFFMAX) - -#define S_PERSHIFTMAX 8 -#define M_PERSHIFTMAX 0xf -#define V_PERSHIFTMAX(x) ((x) << S_PERSHIFTMAX) - -#define S_KEEPALIVEMAX 0 - -#define M_KEEPALIVEMAX 0xff - -#define V_KEEPALIVEMAX(x) ((x) << S_KEEPALIVEMAX) - -#define A_TP_MTU_PORT_TABLE 0x3d0 - -#define A_TP_CCTRL_TABLE 0x3dc - -#define A_TP_MTU_TABLE 0x3e4 - -#define A_TP_RSS_MAP_TABLE 0x3e8 - -#define A_TP_RSS_LKP_TABLE 0x3ec - -#define A_TP_RSS_CONFIG 0x3f0 - -#define S_TNL4TUPEN 29 -#define V_TNL4TUPEN(x) ((x) << S_TNL4TUPEN) -#define F_TNL4TUPEN V_TNL4TUPEN(1U) - -#define S_TNL2TUPEN 28 -#define V_TNL2TUPEN(x) ((x) << S_TNL2TUPEN) -#define F_TNL2TUPEN V_TNL2TUPEN(1U) - -#define S_TNLPRTEN 26 -#define V_TNLPRTEN(x) ((x) << S_TNLPRTEN) -#define F_TNLPRTEN V_TNLPRTEN(1U) - -#define S_TNLMAPEN 25 -#define V_TNLMAPEN(x) ((x) << S_TNLMAPEN) -#define F_TNLMAPEN V_TNLMAPEN(1U) - -#define S_TNLLKPEN 24 -#define V_TNLLKPEN(x) ((x) << S_TNLLKPEN) -#define F_TNLLKPEN V_TNLLKPEN(1U) - -#define S_RRCPLCPUSIZE 4 -#define M_RRCPLCPUSIZE 0x7 -#define V_RRCPLCPUSIZE(x) ((x) << S_RRCPLCPUSIZE) - -#define S_RQFEEDBACKENABLE 3 -#define V_RQFEEDBACKENABLE(x) ((x) << S_RQFEEDBACKENABLE) -#define F_RQFEEDBACKENABLE V_RQFEEDBACKENABLE(1U) - -#define S_DISABLE 0 - -#define A_TP_TM_PIO_ADDR 0x418 - -#define A_TP_TM_PIO_DATA 0x41c - -#define A_TP_TX_MOD_QUE_TABLE 0x420 - -#define A_TP_TX_RESOURCE_LIMIT 0x424 - -#define A_TP_TX_MOD_QUEUE_REQ_MAP 0x428 - -#define S_TX_MOD_QUEUE_REQ_MAP 0 -#define M_TX_MOD_QUEUE_REQ_MAP 0xff -#define V_TX_MOD_QUEUE_REQ_MAP(x) ((x) << S_TX_MOD_QUEUE_REQ_MAP) - -#define A_TP_TX_MOD_QUEUE_WEIGHT1 0x42c - -#define A_TP_TX_MOD_QUEUE_WEIGHT0 0x430 - -#define A_TP_MOD_CHANNEL_WEIGHT 0x434 - -#define A_TP_PIO_ADDR 0x440 - -#define A_TP_PIO_DATA 0x444 - -#define A_TP_RESET 0x44c - -#define S_FLSTINITENABLE 1 -#define V_FLSTINITENABLE(x) ((x) << S_FLSTINITENABLE) -#define F_FLSTINITENABLE V_FLSTINITENABLE(1U) - -#define S_TPRESET 0 -#define V_TPRESET(x) ((x) << S_TPRESET) -#define F_TPRESET V_TPRESET(1U) - -#define A_TP_CMM_MM_RX_FLST_BASE 0x460 - -#define A_TP_CMM_MM_TX_FLST_BASE 0x464 - -#define A_TP_CMM_MM_PS_FLST_BASE 0x468 - -#define A_TP_MIB_INDEX 0x450 - -#define A_TP_MIB_RDATA 0x454 - -#define A_TP_CMM_MM_MAX_PSTRUCT 0x46c - -#define A_TP_INT_ENABLE 0x470 - -#define A_TP_INT_CAUSE 0x474 - -#define A_TP_TX_MOD_Q1_Q0_RATE_LIMIT 0x8 - -#define A_TP_TX_DROP_CFG_CH0 0x12b - -#define A_TP_TX_DROP_MODE 0x12f - -#define A_TP_EGRESS_CONFIG 0x145 - -#define S_REWRITEFORCETOSIZE 0 -#define V_REWRITEFORCETOSIZE(x) ((x) << S_REWRITEFORCETOSIZE) -#define F_REWRITEFORCETOSIZE V_REWRITEFORCETOSIZE(1U) - -#define A_TP_TX_TRC_KEY0 0x20 - -#define A_TP_RX_TRC_KEY0 0x120 - -#define A_ULPRX_CTL 0x500 - -#define S_ROUND_ROBIN 4 -#define V_ROUND_ROBIN(x) ((x) << S_ROUND_ROBIN) -#define F_ROUND_ROBIN V_ROUND_ROBIN(1U) - -#define A_ULPRX_INT_ENABLE 0x504 - -#define S_PARERR 0 -#define V_PARERR(x) ((x) << S_PARERR) -#define F_PARERR V_PARERR(1U) - -#define A_ULPRX_INT_CAUSE 0x508 - -#define A_ULPRX_ISCSI_LLIMIT 0x50c - -#define A_ULPRX_ISCSI_ULIMIT 0x510 - -#define A_ULPRX_ISCSI_TAGMASK 0x514 - -#define A_ULPRX_TDDP_LLIMIT 0x51c - -#define A_ULPRX_TDDP_ULIMIT 0x520 - -#define A_ULPRX_STAG_LLIMIT 0x52c - -#define A_ULPRX_STAG_ULIMIT 0x530 - -#define A_ULPRX_RQ_LLIMIT 0x534 -#define A_ULPRX_RQ_LLIMIT 0x534 - -#define A_ULPRX_RQ_ULIMIT 0x538 -#define A_ULPRX_RQ_ULIMIT 0x538 - -#define A_ULPRX_PBL_LLIMIT 0x53c - -#define A_ULPRX_PBL_ULIMIT 0x540 -#define A_ULPRX_PBL_ULIMIT 0x540 - -#define A_ULPRX_TDDP_TAGMASK 0x524 - -#define A_ULPRX_RQ_LLIMIT 0x534 -#define A_ULPRX_RQ_LLIMIT 0x534 - -#define A_ULPRX_RQ_ULIMIT 0x538 -#define A_ULPRX_RQ_ULIMIT 0x538 - -#define A_ULPRX_PBL_ULIMIT 0x540 -#define A_ULPRX_PBL_ULIMIT 0x540 - -#define A_ULPTX_CONFIG 0x580 - -#define S_CFG_RR_ARB 0 -#define V_CFG_RR_ARB(x) ((x) << S_CFG_RR_ARB) -#define F_CFG_RR_ARB V_CFG_RR_ARB(1U) - -#define A_ULPTX_INT_ENABLE 0x584 - -#define S_PBL_BOUND_ERR_CH1 1 -#define V_PBL_BOUND_ERR_CH1(x) ((x) << S_PBL_BOUND_ERR_CH1) -#define F_PBL_BOUND_ERR_CH1 V_PBL_BOUND_ERR_CH1(1U) - -#define S_PBL_BOUND_ERR_CH0 0 -#define V_PBL_BOUND_ERR_CH0(x) ((x) << S_PBL_BOUND_ERR_CH0) -#define F_PBL_BOUND_ERR_CH0 V_PBL_BOUND_ERR_CH0(1U) - -#define A_ULPTX_INT_CAUSE 0x588 - -#define A_ULPTX_TPT_LLIMIT 0x58c - -#define A_ULPTX_TPT_ULIMIT 0x590 - -#define A_ULPTX_PBL_LLIMIT 0x594 - -#define A_ULPTX_PBL_ULIMIT 0x598 - -#define A_ULPTX_DMA_WEIGHT 0x5ac - -#define S_D1_WEIGHT 16 -#define M_D1_WEIGHT 0xffff -#define V_D1_WEIGHT(x) ((x) << S_D1_WEIGHT) - -#define S_D0_WEIGHT 0 -#define M_D0_WEIGHT 0xffff -#define V_D0_WEIGHT(x) ((x) << S_D0_WEIGHT) - -#define A_PM1_RX_CFG 0x5c0 - -#define A_PM1_RX_INT_ENABLE 0x5d8 - -#define S_ZERO_E_CMD_ERROR 18 -#define V_ZERO_E_CMD_ERROR(x) ((x) << S_ZERO_E_CMD_ERROR) -#define F_ZERO_E_CMD_ERROR V_ZERO_E_CMD_ERROR(1U) - -#define S_IESPI0_FIFO2X_RX_FRAMING_ERROR 17 -#define V_IESPI0_FIFO2X_RX_FRAMING_ERROR(x) ((x) << S_IESPI0_FIFO2X_RX_FRAMING_ERROR) -#define F_IESPI0_FIFO2X_RX_FRAMING_ERROR V_IESPI0_FIFO2X_RX_FRAMING_ERROR(1U) - -#define S_IESPI1_FIFO2X_RX_FRAMING_ERROR 16 -#define V_IESPI1_FIFO2X_RX_FRAMING_ERROR(x) ((x) << S_IESPI1_FIFO2X_RX_FRAMING_ERROR) -#define F_IESPI1_FIFO2X_RX_FRAMING_ERROR V_IESPI1_FIFO2X_RX_FRAMING_ERROR(1U) - -#define S_IESPI0_RX_FRAMING_ERROR 15 -#define V_IESPI0_RX_FRAMING_ERROR(x) ((x) << S_IESPI0_RX_FRAMING_ERROR) -#define F_IESPI0_RX_FRAMING_ERROR V_IESPI0_RX_FRAMING_ERROR(1U) - -#define S_IESPI1_RX_FRAMING_ERROR 14 -#define V_IESPI1_RX_FRAMING_ERROR(x) ((x) << S_IESPI1_RX_FRAMING_ERROR) -#define F_IESPI1_RX_FRAMING_ERROR V_IESPI1_RX_FRAMING_ERROR(1U) - -#define S_IESPI0_TX_FRAMING_ERROR 13 -#define V_IESPI0_TX_FRAMING_ERROR(x) ((x) << S_IESPI0_TX_FRAMING_ERROR) -#define F_IESPI0_TX_FRAMING_ERROR V_IESPI0_TX_FRAMING_ERROR(1U) - -#define S_IESPI1_TX_FRAMING_ERROR 12 -#define V_IESPI1_TX_FRAMING_ERROR(x) ((x) << S_IESPI1_TX_FRAMING_ERROR) -#define F_IESPI1_TX_FRAMING_ERROR V_IESPI1_TX_FRAMING_ERROR(1U) - -#define S_OCSPI0_RX_FRAMING_ERROR 11 -#define V_OCSPI0_RX_FRAMING_ERROR(x) ((x) << S_OCSPI0_RX_FRAMING_ERROR) -#define F_OCSPI0_RX_FRAMING_ERROR V_OCSPI0_RX_FRAMING_ERROR(1U) - -#define S_OCSPI1_RX_FRAMING_ERROR 10 -#define V_OCSPI1_RX_FRAMING_ERROR(x) ((x) << S_OCSPI1_RX_FRAMING_ERROR) -#define F_OCSPI1_RX_FRAMING_ERROR V_OCSPI1_RX_FRAMING_ERROR(1U) - -#define S_OCSPI0_TX_FRAMING_ERROR 9 -#define V_OCSPI0_TX_FRAMING_ERROR(x) ((x) << S_OCSPI0_TX_FRAMING_ERROR) -#define F_OCSPI0_TX_FRAMING_ERROR V_OCSPI0_TX_FRAMING_ERROR(1U) - -#define S_OCSPI1_TX_FRAMING_ERROR 8 -#define V_OCSPI1_TX_FRAMING_ERROR(x) ((x) << S_OCSPI1_TX_FRAMING_ERROR) -#define F_OCSPI1_TX_FRAMING_ERROR V_OCSPI1_TX_FRAMING_ERROR(1U) - -#define S_OCSPI0_OFIFO2X_TX_FRAMING_ERROR 7 -#define V_OCSPI0_OFIFO2X_TX_FRAMING_ERROR(x) ((x) << S_OCSPI0_OFIFO2X_TX_FRAMING_ERROR) -#define F_OCSPI0_OFIFO2X_TX_FRAMING_ERROR V_OCSPI0_OFIFO2X_TX_FRAMING_ERROR(1U) - -#define S_OCSPI1_OFIFO2X_TX_FRAMING_ERROR 6 -#define V_OCSPI1_OFIFO2X_TX_FRAMING_ERROR(x) ((x) << S_OCSPI1_OFIFO2X_TX_FRAMING_ERROR) -#define F_OCSPI1_OFIFO2X_TX_FRAMING_ERROR V_OCSPI1_OFIFO2X_TX_FRAMING_ERROR(1U) - -#define S_IESPI_PAR_ERROR 3 -#define M_IESPI_PAR_ERROR 0x7 - -#define V_IESPI_PAR_ERROR(x) ((x) << S_IESPI_PAR_ERROR) - -#define S_OCSPI_PAR_ERROR 0 -#define M_OCSPI_PAR_ERROR 0x7 - -#define V_OCSPI_PAR_ERROR(x) ((x) << S_OCSPI_PAR_ERROR) - -#define A_PM1_RX_INT_CAUSE 0x5dc - -#define A_PM1_TX_CFG 0x5e0 - -#define A_PM1_TX_INT_ENABLE 0x5f8 - -#define S_ZERO_C_CMD_ERROR 18 -#define V_ZERO_C_CMD_ERROR(x) ((x) << S_ZERO_C_CMD_ERROR) -#define F_ZERO_C_CMD_ERROR V_ZERO_C_CMD_ERROR(1U) - -#define S_ICSPI0_FIFO2X_RX_FRAMING_ERROR 17 -#define V_ICSPI0_FIFO2X_RX_FRAMING_ERROR(x) ((x) << S_ICSPI0_FIFO2X_RX_FRAMING_ERROR) -#define F_ICSPI0_FIFO2X_RX_FRAMING_ERROR V_ICSPI0_FIFO2X_RX_FRAMING_ERROR(1U) - -#define S_ICSPI1_FIFO2X_RX_FRAMING_ERROR 16 -#define V_ICSPI1_FIFO2X_RX_FRAMING_ERROR(x) ((x) << S_ICSPI1_FIFO2X_RX_FRAMING_ERROR) -#define F_ICSPI1_FIFO2X_RX_FRAMING_ERROR V_ICSPI1_FIFO2X_RX_FRAMING_ERROR(1U) - -#define S_ICSPI0_RX_FRAMING_ERROR 15 -#define V_ICSPI0_RX_FRAMING_ERROR(x) ((x) << S_ICSPI0_RX_FRAMING_ERROR) -#define F_ICSPI0_RX_FRAMING_ERROR V_ICSPI0_RX_FRAMING_ERROR(1U) - -#define S_ICSPI1_RX_FRAMING_ERROR 14 -#define V_ICSPI1_RX_FRAMING_ERROR(x) ((x) << S_ICSPI1_RX_FRAMING_ERROR) -#define F_ICSPI1_RX_FRAMING_ERROR V_ICSPI1_RX_FRAMING_ERROR(1U) - -#define S_ICSPI0_TX_FRAMING_ERROR 13 -#define V_ICSPI0_TX_FRAMING_ERROR(x) ((x) << S_ICSPI0_TX_FRAMING_ERROR) -#define F_ICSPI0_TX_FRAMING_ERROR V_ICSPI0_TX_FRAMING_ERROR(1U) - -#define S_ICSPI1_TX_FRAMING_ERROR 12 -#define V_ICSPI1_TX_FRAMING_ERROR(x) ((x) << S_ICSPI1_TX_FRAMING_ERROR) -#define F_ICSPI1_TX_FRAMING_ERROR V_ICSPI1_TX_FRAMING_ERROR(1U) - -#define S_OESPI0_RX_FRAMING_ERROR 11 -#define V_OESPI0_RX_FRAMING_ERROR(x) ((x) << S_OESPI0_RX_FRAMING_ERROR) -#define F_OESPI0_RX_FRAMING_ERROR V_OESPI0_RX_FRAMING_ERROR(1U) - -#define S_OESPI1_RX_FRAMING_ERROR 10 -#define V_OESPI1_RX_FRAMING_ERROR(x) ((x) << S_OESPI1_RX_FRAMING_ERROR) -#define F_OESPI1_RX_FRAMING_ERROR V_OESPI1_RX_FRAMING_ERROR(1U) - -#define S_OESPI0_TX_FRAMING_ERROR 9 -#define V_OESPI0_TX_FRAMING_ERROR(x) ((x) << S_OESPI0_TX_FRAMING_ERROR) -#define F_OESPI0_TX_FRAMING_ERROR V_OESPI0_TX_FRAMING_ERROR(1U) - -#define S_OESPI1_TX_FRAMING_ERROR 8 -#define V_OESPI1_TX_FRAMING_ERROR(x) ((x) << S_OESPI1_TX_FRAMING_ERROR) -#define F_OESPI1_TX_FRAMING_ERROR V_OESPI1_TX_FRAMING_ERROR(1U) - -#define S_OESPI0_OFIFO2X_TX_FRAMING_ERROR 7 -#define V_OESPI0_OFIFO2X_TX_FRAMING_ERROR(x) ((x) << S_OESPI0_OFIFO2X_TX_FRAMING_ERROR) -#define F_OESPI0_OFIFO2X_TX_FRAMING_ERROR V_OESPI0_OFIFO2X_TX_FRAMING_ERROR(1U) - -#define S_OESPI1_OFIFO2X_TX_FRAMING_ERROR 6 -#define V_OESPI1_OFIFO2X_TX_FRAMING_ERROR(x) ((x) << S_OESPI1_OFIFO2X_TX_FRAMING_ERROR) -#define F_OESPI1_OFIFO2X_TX_FRAMING_ERROR V_OESPI1_OFIFO2X_TX_FRAMING_ERROR(1U) - -#define S_ICSPI_PAR_ERROR 3 -#define M_ICSPI_PAR_ERROR 0x7 - -#define V_ICSPI_PAR_ERROR(x) ((x) << S_ICSPI_PAR_ERROR) - -#define S_OESPI_PAR_ERROR 0 -#define M_OESPI_PAR_ERROR 0x7 - -#define V_OESPI_PAR_ERROR(x) ((x) << S_OESPI_PAR_ERROR) - -#define A_PM1_TX_INT_CAUSE 0x5fc - -#define A_MPS_CFG 0x600 - -#define S_TPRXPORTEN 4 -#define V_TPRXPORTEN(x) ((x) << S_TPRXPORTEN) -#define F_TPRXPORTEN V_TPRXPORTEN(1U) - -#define S_TPTXPORT1EN 3 -#define V_TPTXPORT1EN(x) ((x) << S_TPTXPORT1EN) -#define F_TPTXPORT1EN V_TPTXPORT1EN(1U) - -#define S_TPTXPORT0EN 2 -#define V_TPTXPORT0EN(x) ((x) << S_TPTXPORT0EN) -#define F_TPTXPORT0EN V_TPTXPORT0EN(1U) - -#define S_PORT1ACTIVE 1 -#define V_PORT1ACTIVE(x) ((x) << S_PORT1ACTIVE) -#define F_PORT1ACTIVE V_PORT1ACTIVE(1U) - -#define S_PORT0ACTIVE 0 -#define V_PORT0ACTIVE(x) ((x) << S_PORT0ACTIVE) -#define F_PORT0ACTIVE V_PORT0ACTIVE(1U) - -#define S_ENFORCEPKT 11 -#define V_ENFORCEPKT(x) ((x) << S_ENFORCEPKT) -#define F_ENFORCEPKT V_ENFORCEPKT(1U) - -#define A_MPS_INT_ENABLE 0x61c - -#define S_MCAPARERRENB 6 -#define M_MCAPARERRENB 0x7 - -#define V_MCAPARERRENB(x) ((x) << S_MCAPARERRENB) - -#define S_RXTPPARERRENB 4 -#define M_RXTPPARERRENB 0x3 - -#define V_RXTPPARERRENB(x) ((x) << S_RXTPPARERRENB) - -#define S_TX1TPPARERRENB 2 -#define M_TX1TPPARERRENB 0x3 - -#define V_TX1TPPARERRENB(x) ((x) << S_TX1TPPARERRENB) - -#define S_TX0TPPARERRENB 0 -#define M_TX0TPPARERRENB 0x3 - -#define V_TX0TPPARERRENB(x) ((x) << S_TX0TPPARERRENB) - -#define A_MPS_INT_CAUSE 0x620 - -#define S_MCAPARERR 6 -#define M_MCAPARERR 0x7 - -#define V_MCAPARERR(x) ((x) << S_MCAPARERR) - -#define S_RXTPPARERR 4 -#define M_RXTPPARERR 0x3 - -#define V_RXTPPARERR(x) ((x) << S_RXTPPARERR) - -#define S_TX1TPPARERR 2 -#define M_TX1TPPARERR 0x3 - -#define V_TX1TPPARERR(x) ((x) << S_TX1TPPARERR) - -#define S_TX0TPPARERR 0 -#define M_TX0TPPARERR 0x3 - -#define V_TX0TPPARERR(x) ((x) << S_TX0TPPARERR) - -#define A_CPL_SWITCH_CNTRL 0x640 - -#define A_CPL_INTR_ENABLE 0x650 - -#define S_CIM_OVFL_ERROR 4 -#define V_CIM_OVFL_ERROR(x) ((x) << S_CIM_OVFL_ERROR) -#define F_CIM_OVFL_ERROR V_CIM_OVFL_ERROR(1U) - -#define S_TP_FRAMING_ERROR 3 -#define V_TP_FRAMING_ERROR(x) ((x) << S_TP_FRAMING_ERROR) -#define F_TP_FRAMING_ERROR V_TP_FRAMING_ERROR(1U) - -#define S_SGE_FRAMING_ERROR 2 -#define V_SGE_FRAMING_ERROR(x) ((x) << S_SGE_FRAMING_ERROR) -#define F_SGE_FRAMING_ERROR V_SGE_FRAMING_ERROR(1U) - -#define S_CIM_FRAMING_ERROR 1 -#define V_CIM_FRAMING_ERROR(x) ((x) << S_CIM_FRAMING_ERROR) -#define F_CIM_FRAMING_ERROR V_CIM_FRAMING_ERROR(1U) - -#define S_ZERO_SWITCH_ERROR 0 -#define V_ZERO_SWITCH_ERROR(x) ((x) << S_ZERO_SWITCH_ERROR) -#define F_ZERO_SWITCH_ERROR V_ZERO_SWITCH_ERROR(1U) - -#define A_CPL_INTR_CAUSE 0x654 - -#define A_CPL_MAP_TBL_DATA 0x65c - -#define A_SMB_GLOBAL_TIME_CFG 0x660 - -#define A_I2C_CFG 0x6a0 - -#define S_I2C_CLKDIV 0 -#define M_I2C_CLKDIV 0xfff -#define V_I2C_CLKDIV(x) ((x) << S_I2C_CLKDIV) - -#define A_MI1_CFG 0x6b0 - -#define S_CLKDIV 5 -#define M_CLKDIV 0xff -#define V_CLKDIV(x) ((x) << S_CLKDIV) - -#define S_ST 3 - -#define M_ST 0x3 - -#define V_ST(x) ((x) << S_ST) - -#define G_ST(x) (((x) >> S_ST) & M_ST) - -#define S_PREEN 2 -#define V_PREEN(x) ((x) << S_PREEN) -#define F_PREEN V_PREEN(1U) - -#define S_MDIINV 1 -#define V_MDIINV(x) ((x) << S_MDIINV) -#define F_MDIINV V_MDIINV(1U) - -#define S_MDIEN 0 -#define V_MDIEN(x) ((x) << S_MDIEN) -#define F_MDIEN V_MDIEN(1U) - -#define A_MI1_ADDR 0x6b4 - -#define S_PHYADDR 5 -#define M_PHYADDR 0x1f -#define V_PHYADDR(x) ((x) << S_PHYADDR) - -#define S_REGADDR 0 -#define M_REGADDR 0x1f -#define V_REGADDR(x) ((x) << S_REGADDR) - -#define A_MI1_DATA 0x6b8 - -#define A_MI1_OP 0x6bc - -#define S_MDI_OP 0 -#define M_MDI_OP 0x3 -#define V_MDI_OP(x) ((x) << S_MDI_OP) - -#define A_SF_DATA 0x6d8 - -#define A_SF_OP 0x6dc - -#define S_BYTECNT 1 -#define M_BYTECNT 0x3 -#define V_BYTECNT(x) ((x) << S_BYTECNT) - -#define A_PL_INT_ENABLE0 0x6e0 - -#define S_T3DBG 23 -#define V_T3DBG(x) ((x) << S_T3DBG) -#define F_T3DBG V_T3DBG(1U) - -#define S_XGMAC0_1 20 -#define V_XGMAC0_1(x) ((x) << S_XGMAC0_1) -#define F_XGMAC0_1 V_XGMAC0_1(1U) - -#define S_XGMAC0_0 19 -#define V_XGMAC0_0(x) ((x) << S_XGMAC0_0) -#define F_XGMAC0_0 V_XGMAC0_0(1U) - -#define S_MC5A 18 -#define V_MC5A(x) ((x) << S_MC5A) -#define F_MC5A V_MC5A(1U) - -#define S_CPL_SWITCH 12 -#define V_CPL_SWITCH(x) ((x) << S_CPL_SWITCH) -#define F_CPL_SWITCH V_CPL_SWITCH(1U) - -#define S_MPS0 11 -#define V_MPS0(x) ((x) << S_MPS0) -#define F_MPS0 V_MPS0(1U) - -#define S_PM1_TX 10 -#define V_PM1_TX(x) ((x) << S_PM1_TX) -#define F_PM1_TX V_PM1_TX(1U) - -#define S_PM1_RX 9 -#define V_PM1_RX(x) ((x) << S_PM1_RX) -#define F_PM1_RX V_PM1_RX(1U) - -#define S_ULP2_TX 8 -#define V_ULP2_TX(x) ((x) << S_ULP2_TX) -#define F_ULP2_TX V_ULP2_TX(1U) - -#define S_ULP2_RX 7 -#define V_ULP2_RX(x) ((x) << S_ULP2_RX) -#define F_ULP2_RX V_ULP2_RX(1U) - -#define S_TP1 6 -#define V_TP1(x) ((x) << S_TP1) -#define F_TP1 V_TP1(1U) - -#define S_CIM 5 -#define V_CIM(x) ((x) << S_CIM) -#define F_CIM V_CIM(1U) - -#define S_MC7_CM 4 -#define V_MC7_CM(x) ((x) << S_MC7_CM) -#define F_MC7_CM V_MC7_CM(1U) - -#define S_MC7_PMTX 3 -#define V_MC7_PMTX(x) ((x) << S_MC7_PMTX) -#define F_MC7_PMTX V_MC7_PMTX(1U) - -#define S_MC7_PMRX 2 -#define V_MC7_PMRX(x) ((x) << S_MC7_PMRX) -#define F_MC7_PMRX V_MC7_PMRX(1U) - -#define S_PCIM0 1 -#define V_PCIM0(x) ((x) << S_PCIM0) -#define F_PCIM0 V_PCIM0(1U) - -#define S_SGE3 0 -#define V_SGE3(x) ((x) << S_SGE3) -#define F_SGE3 V_SGE3(1U) - -#define A_PL_INT_CAUSE0 0x6e4 - -#define A_PL_RST 0x6f0 - -#define S_CRSTWRM 1 -#define V_CRSTWRM(x) ((x) << S_CRSTWRM) -#define F_CRSTWRM V_CRSTWRM(1U) - -#define A_PL_REV 0x6f4 - -#define A_PL_CLI 0x6f8 - -#define A_MC5_DB_CONFIG 0x704 - -#define S_TMTYPEHI 30 -#define V_TMTYPEHI(x) ((x) << S_TMTYPEHI) -#define F_TMTYPEHI V_TMTYPEHI(1U) - -#define S_TMPARTSIZE 28 -#define M_TMPARTSIZE 0x3 -#define V_TMPARTSIZE(x) ((x) << S_TMPARTSIZE) -#define G_TMPARTSIZE(x) (((x) >> S_TMPARTSIZE) & M_TMPARTSIZE) - -#define S_TMTYPE 26 -#define M_TMTYPE 0x3 -#define V_TMTYPE(x) ((x) << S_TMTYPE) -#define G_TMTYPE(x) (((x) >> S_TMTYPE) & M_TMTYPE) - -#define S_COMPEN 17 -#define V_COMPEN(x) ((x) << S_COMPEN) -#define F_COMPEN V_COMPEN(1U) - -#define S_PRTYEN 6 -#define V_PRTYEN(x) ((x) << S_PRTYEN) -#define F_PRTYEN V_PRTYEN(1U) - -#define S_MBUSEN 5 -#define V_MBUSEN(x) ((x) << S_MBUSEN) -#define F_MBUSEN V_MBUSEN(1U) - -#define S_DBGIEN 4 -#define V_DBGIEN(x) ((x) << S_DBGIEN) -#define F_DBGIEN V_DBGIEN(1U) - -#define S_TMRDY 2 -#define V_TMRDY(x) ((x) << S_TMRDY) -#define F_TMRDY V_TMRDY(1U) - -#define S_TMRST 1 -#define V_TMRST(x) ((x) << S_TMRST) -#define F_TMRST V_TMRST(1U) - -#define S_TMMODE 0 -#define V_TMMODE(x) ((x) << S_TMMODE) -#define F_TMMODE V_TMMODE(1U) - -#define F_TMMODE V_TMMODE(1U) - -#define A_MC5_DB_ROUTING_TABLE_INDEX 0x70c - -#define A_MC5_DB_FILTER_TABLE 0x710 - -#define A_MC5_DB_SERVER_INDEX 0x714 - -#define A_MC5_DB_RSP_LATENCY 0x720 - -#define S_RDLAT 16 -#define M_RDLAT 0x1f -#define V_RDLAT(x) ((x) << S_RDLAT) - -#define S_LRNLAT 8 -#define M_LRNLAT 0x1f -#define V_LRNLAT(x) ((x) << S_LRNLAT) - -#define S_SRCHLAT 0 -#define M_SRCHLAT 0x1f -#define V_SRCHLAT(x) ((x) << S_SRCHLAT) - -#define A_MC5_DB_PART_ID_INDEX 0x72c - -#define A_MC5_DB_INT_ENABLE 0x740 - -#define S_DELACTEMPTY 18 -#define V_DELACTEMPTY(x) ((x) << S_DELACTEMPTY) -#define F_DELACTEMPTY V_DELACTEMPTY(1U) - -#define S_DISPQPARERR 17 -#define V_DISPQPARERR(x) ((x) << S_DISPQPARERR) -#define F_DISPQPARERR V_DISPQPARERR(1U) - -#define S_REQQPARERR 16 -#define V_REQQPARERR(x) ((x) << S_REQQPARERR) -#define F_REQQPARERR V_REQQPARERR(1U) - -#define S_UNKNOWNCMD 15 -#define V_UNKNOWNCMD(x) ((x) << S_UNKNOWNCMD) -#define F_UNKNOWNCMD V_UNKNOWNCMD(1U) - -#define S_NFASRCHFAIL 8 -#define V_NFASRCHFAIL(x) ((x) << S_NFASRCHFAIL) -#define F_NFASRCHFAIL V_NFASRCHFAIL(1U) - -#define S_ACTRGNFULL 7 -#define V_ACTRGNFULL(x) ((x) << S_ACTRGNFULL) -#define F_ACTRGNFULL V_ACTRGNFULL(1U) - -#define S_PARITYERR 6 -#define V_PARITYERR(x) ((x) << S_PARITYERR) -#define F_PARITYERR V_PARITYERR(1U) - -#define A_MC5_DB_INT_CAUSE 0x744 - -#define A_MC5_DB_DBGI_CONFIG 0x774 - -#define A_MC5_DB_DBGI_REQ_CMD 0x778 - -#define A_MC5_DB_DBGI_REQ_ADDR0 0x77c - -#define A_MC5_DB_DBGI_REQ_ADDR1 0x780 - -#define A_MC5_DB_DBGI_REQ_ADDR2 0x784 - -#define A_MC5_DB_DBGI_REQ_DATA0 0x788 - -#define A_MC5_DB_DBGI_REQ_DATA1 0x78c - -#define A_MC5_DB_DBGI_REQ_DATA2 0x790 - -#define A_MC5_DB_DBGI_RSP_STATUS 0x7b0 - -#define S_DBGIRSPVALID 0 -#define V_DBGIRSPVALID(x) ((x) << S_DBGIRSPVALID) -#define F_DBGIRSPVALID V_DBGIRSPVALID(1U) - -#define A_MC5_DB_DBGI_RSP_DATA0 0x7b4 - -#define A_MC5_DB_DBGI_RSP_DATA1 0x7b8 - -#define A_MC5_DB_DBGI_RSP_DATA2 0x7bc - -#define A_MC5_DB_POPEN_DATA_WR_CMD 0x7cc - -#define A_MC5_DB_POPEN_MASK_WR_CMD 0x7d0 - -#define A_MC5_DB_AOPEN_SRCH_CMD 0x7d4 - -#define A_MC5_DB_AOPEN_LRN_CMD 0x7d8 - -#define A_MC5_DB_SYN_SRCH_CMD 0x7dc - -#define A_MC5_DB_SYN_LRN_CMD 0x7e0 - -#define A_MC5_DB_ACK_SRCH_CMD 0x7e4 - -#define A_MC5_DB_ACK_LRN_CMD 0x7e8 - -#define A_MC5_DB_ILOOKUP_CMD 0x7ec - -#define A_MC5_DB_ELOOKUP_CMD 0x7f0 - -#define A_MC5_DB_DATA_WRITE_CMD 0x7f4 - -#define A_MC5_DB_DATA_READ_CMD 0x7f8 - -#define XGMAC0_0_BASE_ADDR 0x800 - -#define A_XGM_TX_CTRL 0x800 - -#define S_TXEN 0 -#define V_TXEN(x) ((x) << S_TXEN) -#define F_TXEN V_TXEN(1U) - -#define A_XGM_TX_CFG 0x804 - -#define S_TXPAUSEEN 0 -#define V_TXPAUSEEN(x) ((x) << S_TXPAUSEEN) -#define F_TXPAUSEEN V_TXPAUSEEN(1U) - -#define A_XGM_RX_CTRL 0x80c - -#define S_RXEN 0 -#define V_RXEN(x) ((x) << S_RXEN) -#define F_RXEN V_RXEN(1U) - -#define A_XGM_RX_CFG 0x810 - -#define S_DISPAUSEFRAMES 9 -#define V_DISPAUSEFRAMES(x) ((x) << S_DISPAUSEFRAMES) -#define F_DISPAUSEFRAMES V_DISPAUSEFRAMES(1U) - -#define S_EN1536BFRAMES 8 -#define V_EN1536BFRAMES(x) ((x) << S_EN1536BFRAMES) -#define F_EN1536BFRAMES V_EN1536BFRAMES(1U) - -#define S_ENJUMBO 7 -#define V_ENJUMBO(x) ((x) << S_ENJUMBO) -#define F_ENJUMBO V_ENJUMBO(1U) - -#define S_RMFCS 6 -#define V_RMFCS(x) ((x) << S_RMFCS) -#define F_RMFCS V_RMFCS(1U) - -#define S_ENHASHMCAST 2 -#define V_ENHASHMCAST(x) ((x) << S_ENHASHMCAST) -#define F_ENHASHMCAST V_ENHASHMCAST(1U) - -#define S_COPYALLFRAMES 0 -#define V_COPYALLFRAMES(x) ((x) << S_COPYALLFRAMES) -#define F_COPYALLFRAMES V_COPYALLFRAMES(1U) - -#define A_XGM_RX_HASH_LOW 0x814 - -#define A_XGM_RX_HASH_HIGH 0x818 - -#define A_XGM_RX_EXACT_MATCH_LOW_1 0x81c - -#define A_XGM_RX_EXACT_MATCH_HIGH_1 0x820 - -#define A_XGM_RX_EXACT_MATCH_LOW_2 0x824 - -#define A_XGM_RX_EXACT_MATCH_LOW_3 0x82c - -#define A_XGM_RX_EXACT_MATCH_LOW_4 0x834 - -#define A_XGM_RX_EXACT_MATCH_LOW_5 0x83c - -#define A_XGM_RX_EXACT_MATCH_LOW_6 0x844 - -#define A_XGM_RX_EXACT_MATCH_LOW_7 0x84c - -#define A_XGM_RX_EXACT_MATCH_LOW_8 0x854 - -#define A_XGM_STAT_CTRL 0x880 - -#define S_CLRSTATS 2 -#define V_CLRSTATS(x) ((x) << S_CLRSTATS) -#define F_CLRSTATS V_CLRSTATS(1U) - -#define A_XGM_RXFIFO_CFG 0x884 - -#define S_RXFIFOPAUSEHWM 17 -#define M_RXFIFOPAUSEHWM 0xfff - -#define V_RXFIFOPAUSEHWM(x) ((x) << S_RXFIFOPAUSEHWM) - -#define G_RXFIFOPAUSEHWM(x) (((x) >> S_RXFIFOPAUSEHWM) & M_RXFIFOPAUSEHWM) - -#define S_RXFIFOPAUSELWM 5 -#define M_RXFIFOPAUSELWM 0xfff - -#define V_RXFIFOPAUSELWM(x) ((x) << S_RXFIFOPAUSELWM) - -#define G_RXFIFOPAUSELWM(x) (((x) >> S_RXFIFOPAUSELWM) & M_RXFIFOPAUSELWM) - -#define S_RXSTRFRWRD 1 -#define V_RXSTRFRWRD(x) ((x) << S_RXSTRFRWRD) -#define F_RXSTRFRWRD V_RXSTRFRWRD(1U) - -#define S_DISERRFRAMES 0 -#define V_DISERRFRAMES(x) ((x) << S_DISERRFRAMES) -#define F_DISERRFRAMES V_DISERRFRAMES(1U) - -#define A_XGM_TXFIFO_CFG 0x888 - -#define S_TXFIFOTHRESH 4 -#define M_TXFIFOTHRESH 0x1ff - -#define V_TXFIFOTHRESH(x) ((x) << S_TXFIFOTHRESH) - -#define A_XGM_SERDES_CTRL 0x890 -#define A_XGM_SERDES_CTRL0 0x8e0 - -#define S_SERDESRESET_ 24 -#define V_SERDESRESET_(x) ((x) << S_SERDESRESET_) -#define F_SERDESRESET_ V_SERDESRESET_(1U) - -#define S_RXENABLE 4 -#define V_RXENABLE(x) ((x) << S_RXENABLE) -#define F_RXENABLE V_RXENABLE(1U) - -#define S_TXENABLE 3 -#define V_TXENABLE(x) ((x) << S_TXENABLE) -#define F_TXENABLE V_TXENABLE(1U) - -#define A_XGM_PAUSE_TIMER 0x890 - -#define A_XGM_RGMII_IMP 0x89c - -#define S_XGM_IMPSETUPDATE 6 -#define V_XGM_IMPSETUPDATE(x) ((x) << S_XGM_IMPSETUPDATE) -#define F_XGM_IMPSETUPDATE V_XGM_IMPSETUPDATE(1U) - -#define S_RGMIIIMPPD 3 -#define M_RGMIIIMPPD 0x7 -#define V_RGMIIIMPPD(x) ((x) << S_RGMIIIMPPD) - -#define S_RGMIIIMPPU 0 -#define M_RGMIIIMPPU 0x7 -#define V_RGMIIIMPPU(x) ((x) << S_RGMIIIMPPU) - -#define S_CALRESET 8 -#define V_CALRESET(x) ((x) << S_CALRESET) -#define F_CALRESET V_CALRESET(1U) - -#define S_CALUPDATE 7 -#define V_CALUPDATE(x) ((x) << S_CALUPDATE) -#define F_CALUPDATE V_CALUPDATE(1U) - -#define A_XGM_XAUI_IMP 0x8a0 - -#define S_CALBUSY 31 -#define V_CALBUSY(x) ((x) << S_CALBUSY) -#define F_CALBUSY V_CALBUSY(1U) - -#define S_XGM_CALFAULT 29 -#define V_XGM_CALFAULT(x) ((x) << S_XGM_CALFAULT) -#define F_XGM_CALFAULT V_XGM_CALFAULT(1U) - -#define S_CALIMP 24 -#define M_CALIMP 0x1f -#define V_CALIMP(x) ((x) << S_CALIMP) -#define G_CALIMP(x) (((x) >> S_CALIMP) & M_CALIMP) - -#define S_XAUIIMP 0 -#define M_XAUIIMP 0x7 -#define V_XAUIIMP(x) ((x) << S_XAUIIMP) - -#define A_XGM_RX_MAX_PKT_SIZE 0x8a8 -#define A_XGM_RX_MAX_PKT_SIZE_ERR_CNT 0x9a4 - -#define A_XGM_RESET_CTRL 0x8ac - -#define S_XG2G_RESET_ 3 -#define V_XG2G_RESET_(x) ((x) << S_XG2G_RESET_) -#define F_XG2G_RESET_ V_XG2G_RESET_(1U) - -#define S_RGMII_RESET_ 2 -#define V_RGMII_RESET_(x) ((x) << S_RGMII_RESET_) -#define F_RGMII_RESET_ V_RGMII_RESET_(1U) - -#define S_PCS_RESET_ 1 -#define V_PCS_RESET_(x) ((x) << S_PCS_RESET_) -#define F_PCS_RESET_ V_PCS_RESET_(1U) - -#define S_MAC_RESET_ 0 -#define V_MAC_RESET_(x) ((x) << S_MAC_RESET_) -#define F_MAC_RESET_ V_MAC_RESET_(1U) - -#define A_XGM_PORT_CFG 0x8b8 - -#define S_CLKDIVRESET_ 3 -#define V_CLKDIVRESET_(x) ((x) << S_CLKDIVRESET_) -#define F_CLKDIVRESET_ V_CLKDIVRESET_(1U) - -#define S_PORTSPEED 1 -#define M_PORTSPEED 0x3 - -#define V_PORTSPEED(x) ((x) << S_PORTSPEED) - -#define S_ENRGMII 0 -#define V_ENRGMII(x) ((x) << S_ENRGMII) -#define F_ENRGMII V_ENRGMII(1U) - -#define A_XGM_INT_ENABLE 0x8d4 - -#define S_TXFIFO_PRTY_ERR 17 -#define M_TXFIFO_PRTY_ERR 0x7 - -#define V_TXFIFO_PRTY_ERR(x) ((x) << S_TXFIFO_PRTY_ERR) - -#define S_RXFIFO_PRTY_ERR 14 -#define M_RXFIFO_PRTY_ERR 0x7 - -#define V_RXFIFO_PRTY_ERR(x) ((x) << S_RXFIFO_PRTY_ERR) - -#define S_TXFIFO_UNDERRUN 13 -#define V_TXFIFO_UNDERRUN(x) ((x) << S_TXFIFO_UNDERRUN) -#define F_TXFIFO_UNDERRUN V_TXFIFO_UNDERRUN(1U) - -#define S_RXFIFO_OVERFLOW 12 -#define V_RXFIFO_OVERFLOW(x) ((x) << S_RXFIFO_OVERFLOW) -#define F_RXFIFO_OVERFLOW V_RXFIFO_OVERFLOW(1U) - -#define S_SERDES_LOS 4 -#define M_SERDES_LOS 0xf - -#define V_SERDES_LOS(x) ((x) << S_SERDES_LOS) - -#define S_XAUIPCSCTCERR 3 -#define V_XAUIPCSCTCERR(x) ((x) << S_XAUIPCSCTCERR) -#define F_XAUIPCSCTCERR V_XAUIPCSCTCERR(1U) - -#define S_XAUIPCSALIGNCHANGE 2 -#define V_XAUIPCSALIGNCHANGE(x) ((x) << S_XAUIPCSALIGNCHANGE) -#define F_XAUIPCSALIGNCHANGE V_XAUIPCSALIGNCHANGE(1U) - -#define A_XGM_INT_CAUSE 0x8d8 - -#define A_XGM_XAUI_ACT_CTRL 0x8dc - -#define S_TXACTENABLE 1 -#define V_TXACTENABLE(x) ((x) << S_TXACTENABLE) -#define F_TXACTENABLE V_TXACTENABLE(1U) - -#define A_XGM_SERDES_CTRL0 0x8e0 - -#define S_RESET3 23 -#define V_RESET3(x) ((x) << S_RESET3) -#define F_RESET3 V_RESET3(1U) - -#define S_RESET2 22 -#define V_RESET2(x) ((x) << S_RESET2) -#define F_RESET2 V_RESET2(1U) - -#define S_RESET1 21 -#define V_RESET1(x) ((x) << S_RESET1) -#define F_RESET1 V_RESET1(1U) - -#define S_RESET0 20 -#define V_RESET0(x) ((x) << S_RESET0) -#define F_RESET0 V_RESET0(1U) - -#define S_PWRDN3 19 -#define V_PWRDN3(x) ((x) << S_PWRDN3) -#define F_PWRDN3 V_PWRDN3(1U) - -#define S_PWRDN2 18 -#define V_PWRDN2(x) ((x) << S_PWRDN2) -#define F_PWRDN2 V_PWRDN2(1U) - -#define S_PWRDN1 17 -#define V_PWRDN1(x) ((x) << S_PWRDN1) -#define F_PWRDN1 V_PWRDN1(1U) - -#define S_PWRDN0 16 -#define V_PWRDN0(x) ((x) << S_PWRDN0) -#define F_PWRDN0 V_PWRDN0(1U) - -#define S_RESETPLL23 15 -#define V_RESETPLL23(x) ((x) << S_RESETPLL23) -#define F_RESETPLL23 V_RESETPLL23(1U) - -#define S_RESETPLL01 14 -#define V_RESETPLL01(x) ((x) << S_RESETPLL01) -#define F_RESETPLL01 V_RESETPLL01(1U) - -#define A_XGM_SERDES_STAT0 0x8f0 - -#define S_LOWSIG0 0 -#define V_LOWSIG0(x) ((x) << S_LOWSIG0) -#define F_LOWSIG0 V_LOWSIG0(1U) - -#define A_XGM_SERDES_STAT3 0x8fc - -#define A_XGM_STAT_TX_BYTE_LOW 0x900 - -#define A_XGM_STAT_TX_BYTE_HIGH 0x904 - -#define A_XGM_STAT_TX_FRAME_LOW 0x908 - -#define A_XGM_STAT_TX_FRAME_HIGH 0x90c - -#define A_XGM_STAT_TX_BCAST 0x910 - -#define A_XGM_STAT_TX_MCAST 0x914 - -#define A_XGM_STAT_TX_PAUSE 0x918 - -#define A_XGM_STAT_TX_64B_FRAMES 0x91c - -#define A_XGM_STAT_TX_65_127B_FRAMES 0x920 - -#define A_XGM_STAT_TX_128_255B_FRAMES 0x924 - -#define A_XGM_STAT_TX_256_511B_FRAMES 0x928 - -#define A_XGM_STAT_TX_512_1023B_FRAMES 0x92c - -#define A_XGM_STAT_TX_1024_1518B_FRAMES 0x930 - -#define A_XGM_STAT_TX_1519_MAXB_FRAMES 0x934 - -#define A_XGM_STAT_TX_ERR_FRAMES 0x938 - -#define A_XGM_STAT_RX_BYTES_LOW 0x93c - -#define A_XGM_STAT_RX_BYTES_HIGH 0x940 - -#define A_XGM_STAT_RX_FRAMES_LOW 0x944 - -#define A_XGM_STAT_RX_FRAMES_HIGH 0x948 - -#define A_XGM_STAT_RX_BCAST_FRAMES 0x94c - -#define A_XGM_STAT_RX_MCAST_FRAMES 0x950 - -#define A_XGM_STAT_RX_PAUSE_FRAMES 0x954 - -#define A_XGM_STAT_RX_64B_FRAMES 0x958 - -#define A_XGM_STAT_RX_65_127B_FRAMES 0x95c - -#define A_XGM_STAT_RX_128_255B_FRAMES 0x960 - -#define A_XGM_STAT_RX_256_511B_FRAMES 0x964 - -#define A_XGM_STAT_RX_512_1023B_FRAMES 0x968 - -#define A_XGM_STAT_RX_1024_1518B_FRAMES 0x96c - -#define A_XGM_STAT_RX_1519_MAXB_FRAMES 0x970 - -#define A_XGM_STAT_RX_SHORT_FRAMES 0x974 - -#define A_XGM_STAT_RX_OVERSIZE_FRAMES 0x978 - -#define A_XGM_STAT_RX_JABBER_FRAMES 0x97c - -#define A_XGM_STAT_RX_CRC_ERR_FRAMES 0x980 - -#define A_XGM_STAT_RX_LENGTH_ERR_FRAMES 0x984 - -#define A_XGM_STAT_RX_SYM_CODE_ERR_FRAMES 0x988 - -#define A_XGM_SERDES_STATUS0 0x98c - -#define A_XGM_SERDES_STATUS1 0x990 - -#define S_CMULOCK 31 -#define V_CMULOCK(x) ((x) << S_CMULOCK) -#define F_CMULOCK V_CMULOCK(1U) - -#define A_XGM_RX_MAX_PKT_SIZE_ERR_CNT 0x9a4 - -#define A_XGM_RX_SPI4_SOP_EOP_CNT 0x9ac - -#define XGMAC0_1_BASE_ADDR 0xa00 diff --git a/trunk/drivers/net/cxgb3/sge.c b/trunk/drivers/net/cxgb3/sge.c deleted file mode 100644 index 3f2cf8a07c61..000000000000 --- a/trunk/drivers/net/cxgb3/sge.c +++ /dev/null @@ -1,2681 +0,0 @@ -/* - * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include "common.h" -#include "regs.h" -#include "sge_defs.h" -#include "t3_cpl.h" -#include "firmware_exports.h" - -#define USE_GTS 0 - -#define SGE_RX_SM_BUF_SIZE 1536 -#define SGE_RX_COPY_THRES 256 - -# define SGE_RX_DROP_THRES 16 - -/* - * Period of the Tx buffer reclaim timer. This timer does not need to run - * frequently as Tx buffers are usually reclaimed by new Tx packets. - */ -#define TX_RECLAIM_PERIOD (HZ / 4) - -/* WR size in bytes */ -#define WR_LEN (WR_FLITS * 8) - -/* - * Types of Tx queues in each queue set. Order here matters, do not change. - */ -enum { TXQ_ETH, TXQ_OFLD, TXQ_CTRL }; - -/* Values for sge_txq.flags */ -enum { - TXQ_RUNNING = 1 << 0, /* fetch engine is running */ - TXQ_LAST_PKT_DB = 1 << 1, /* last packet rang the doorbell */ -}; - -struct tx_desc { - u64 flit[TX_DESC_FLITS]; -}; - -struct rx_desc { - __be32 addr_lo; - __be32 len_gen; - __be32 gen2; - __be32 addr_hi; -}; - -struct tx_sw_desc { /* SW state per Tx descriptor */ - struct sk_buff *skb; -}; - -struct rx_sw_desc { /* SW state per Rx descriptor */ - struct sk_buff *skb; - DECLARE_PCI_UNMAP_ADDR(dma_addr); -}; - -struct rsp_desc { /* response queue descriptor */ - struct rss_header rss_hdr; - __be32 flags; - __be32 len_cq; - u8 imm_data[47]; - u8 intr_gen; -}; - -struct unmap_info { /* packet unmapping info, overlays skb->cb */ - int sflit; /* start flit of first SGL entry in Tx descriptor */ - u16 fragidx; /* first page fragment in current Tx descriptor */ - u16 addr_idx; /* buffer index of first SGL entry in descriptor */ - u32 len; /* mapped length of skb main body */ -}; - -/* - * Maps a number of flits to the number of Tx descriptors that can hold them. - * The formula is - * - * desc = 1 + (flits - 2) / (WR_FLITS - 1). - * - * HW allows up to 4 descriptors to be combined into a WR. - */ -static u8 flit_desc_map[] = { - 0, -#if SGE_NUM_GENBITS == 1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 -#elif SGE_NUM_GENBITS == 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, -#else -# error "SGE_NUM_GENBITS must be 1 or 2" -#endif -}; - -static inline struct sge_qset *fl_to_qset(const struct sge_fl *q, int qidx) -{ - return container_of(q, struct sge_qset, fl[qidx]); -} - -static inline struct sge_qset *rspq_to_qset(const struct sge_rspq *q) -{ - return container_of(q, struct sge_qset, rspq); -} - -static inline struct sge_qset *txq_to_qset(const struct sge_txq *q, int qidx) -{ - return container_of(q, struct sge_qset, txq[qidx]); -} - -/** - * refill_rspq - replenish an SGE response queue - * @adapter: the adapter - * @q: the response queue to replenish - * @credits: how many new responses to make available - * - * Replenishes a response queue by making the supplied number of responses - * available to HW. - */ -static inline void refill_rspq(struct adapter *adapter, - const struct sge_rspq *q, unsigned int credits) -{ - t3_write_reg(adapter, A_SG_RSPQ_CREDIT_RETURN, - V_RSPQ(q->cntxt_id) | V_CREDITS(credits)); -} - -/** - * need_skb_unmap - does the platform need unmapping of sk_buffs? - * - * Returns true if the platfrom needs sk_buff unmapping. The compiler - * optimizes away unecessary code if this returns true. - */ -static inline int need_skb_unmap(void) -{ - /* - * This structure is used to tell if the platfrom needs buffer - * unmapping by checking if DECLARE_PCI_UNMAP_ADDR defines anything. - */ - struct dummy { - DECLARE_PCI_UNMAP_ADDR(addr); - }; - - return sizeof(struct dummy) != 0; -} - -/** - * unmap_skb - unmap a packet main body and its page fragments - * @skb: the packet - * @q: the Tx queue containing Tx descriptors for the packet - * @cidx: index of Tx descriptor - * @pdev: the PCI device - * - * Unmap the main body of an sk_buff and its page fragments, if any. - * Because of the fairly complicated structure of our SGLs and the desire - * to conserve space for metadata, we keep the information necessary to - * unmap an sk_buff partly in the sk_buff itself (in its cb), and partly - * in the Tx descriptors (the physical addresses of the various data - * buffers). The send functions initialize the state in skb->cb so we - * can unmap the buffers held in the first Tx descriptor here, and we - * have enough information at this point to update the state for the next - * Tx descriptor. - */ -static inline void unmap_skb(struct sk_buff *skb, struct sge_txq *q, - unsigned int cidx, struct pci_dev *pdev) -{ - const struct sg_ent *sgp; - struct unmap_info *ui = (struct unmap_info *)skb->cb; - int nfrags, frag_idx, curflit, j = ui->addr_idx; - - sgp = (struct sg_ent *)&q->desc[cidx].flit[ui->sflit]; - - if (ui->len) { - pci_unmap_single(pdev, be64_to_cpu(sgp->addr[0]), ui->len, - PCI_DMA_TODEVICE); - ui->len = 0; /* so we know for next descriptor for this skb */ - j = 1; - } - - frag_idx = ui->fragidx; - curflit = ui->sflit + 1 + j; - nfrags = skb_shinfo(skb)->nr_frags; - - while (frag_idx < nfrags && curflit < WR_FLITS) { - pci_unmap_page(pdev, be64_to_cpu(sgp->addr[j]), - skb_shinfo(skb)->frags[frag_idx].size, - PCI_DMA_TODEVICE); - j ^= 1; - if (j == 0) { - sgp++; - curflit++; - } - curflit++; - frag_idx++; - } - - if (frag_idx < nfrags) { /* SGL continues into next Tx descriptor */ - ui->fragidx = frag_idx; - ui->addr_idx = j; - ui->sflit = curflit - WR_FLITS - j; /* sflit can be -1 */ - } -} - -/** - * free_tx_desc - reclaims Tx descriptors and their buffers - * @adapter: the adapter - * @q: the Tx queue to reclaim descriptors from - * @n: the number of descriptors to reclaim - * - * Reclaims Tx descriptors from an SGE Tx queue and frees the associated - * Tx buffers. Called with the Tx queue lock held. - */ -static void free_tx_desc(struct adapter *adapter, struct sge_txq *q, - unsigned int n) -{ - struct tx_sw_desc *d; - struct pci_dev *pdev = adapter->pdev; - unsigned int cidx = q->cidx; - - d = &q->sdesc[cidx]; - while (n--) { - if (d->skb) { /* an SGL is present */ - if (need_skb_unmap()) - unmap_skb(d->skb, q, cidx, pdev); - if (d->skb->priority == cidx) - kfree_skb(d->skb); - } - ++d; - if (++cidx == q->size) { - cidx = 0; - d = q->sdesc; - } - } - q->cidx = cidx; -} - -/** - * reclaim_completed_tx - reclaims completed Tx descriptors - * @adapter: the adapter - * @q: the Tx queue to reclaim completed descriptors from - * - * Reclaims Tx descriptors that the SGE has indicated it has processed, - * and frees the associated buffers if possible. Called with the Tx - * queue's lock held. - */ -static inline void reclaim_completed_tx(struct adapter *adapter, - struct sge_txq *q) -{ - unsigned int reclaim = q->processed - q->cleaned; - - if (reclaim) { - free_tx_desc(adapter, q, reclaim); - q->cleaned += reclaim; - q->in_use -= reclaim; - } -} - -/** - * should_restart_tx - are there enough resources to restart a Tx queue? - * @q: the Tx queue - * - * Checks if there are enough descriptors to restart a suspended Tx queue. - */ -static inline int should_restart_tx(const struct sge_txq *q) -{ - unsigned int r = q->processed - q->cleaned; - - return q->in_use - r < (q->size >> 1); -} - -/** - * free_rx_bufs - free the Rx buffers on an SGE free list - * @pdev: the PCI device associated with the adapter - * @rxq: the SGE free list to clean up - * - * Release the buffers on an SGE free-buffer Rx queue. HW fetching from - * this queue should be stopped before calling this function. - */ -static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) -{ - unsigned int cidx = q->cidx; - - while (q->credits--) { - struct rx_sw_desc *d = &q->sdesc[cidx]; - - pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr), - q->buf_size, PCI_DMA_FROMDEVICE); - kfree_skb(d->skb); - d->skb = NULL; - if (++cidx == q->size) - cidx = 0; - } -} - -/** - * add_one_rx_buf - add a packet buffer to a free-buffer list - * @skb: the buffer to add - * @len: the buffer length - * @d: the HW Rx descriptor to write - * @sd: the SW Rx descriptor to write - * @gen: the generation bit value - * @pdev: the PCI device associated with the adapter - * - * Add a buffer of the given length to the supplied HW and SW Rx - * descriptors. - */ -static inline void add_one_rx_buf(struct sk_buff *skb, unsigned int len, - struct rx_desc *d, struct rx_sw_desc *sd, - unsigned int gen, struct pci_dev *pdev) -{ - dma_addr_t mapping; - - sd->skb = skb; - mapping = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE); - pci_unmap_addr_set(sd, dma_addr, mapping); - - d->addr_lo = cpu_to_be32(mapping); - d->addr_hi = cpu_to_be32((u64) mapping >> 32); - wmb(); - d->len_gen = cpu_to_be32(V_FLD_GEN1(gen)); - d->gen2 = cpu_to_be32(V_FLD_GEN2(gen)); -} - -/** - * refill_fl - refill an SGE free-buffer list - * @adapter: the adapter - * @q: the free-list to refill - * @n: the number of new buffers to allocate - * @gfp: the gfp flags for allocating new buffers - * - * (Re)populate an SGE free-buffer list with up to @n new packet buffers, - * allocated with the supplied gfp flags. The caller must assure that - * @n does not exceed the queue's capacity. - */ -static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) -{ - struct rx_sw_desc *sd = &q->sdesc[q->pidx]; - struct rx_desc *d = &q->desc[q->pidx]; - - while (n--) { - struct sk_buff *skb = alloc_skb(q->buf_size, gfp); - - if (!skb) - break; - - add_one_rx_buf(skb, q->buf_size, d, sd, q->gen, adap->pdev); - d++; - sd++; - if (++q->pidx == q->size) { - q->pidx = 0; - q->gen ^= 1; - sd = q->sdesc; - d = q->desc; - } - q->credits++; - } - - t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); -} - -static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl) -{ - refill_fl(adap, fl, min(16U, fl->size - fl->credits), GFP_ATOMIC); -} - -/** - * recycle_rx_buf - recycle a receive buffer - * @adapter: the adapter - * @q: the SGE free list - * @idx: index of buffer to recycle - * - * Recycles the specified buffer on the given free list by adding it at - * the next available slot on the list. - */ -static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q, - unsigned int idx) -{ - struct rx_desc *from = &q->desc[idx]; - struct rx_desc *to = &q->desc[q->pidx]; - - q->sdesc[q->pidx] = q->sdesc[idx]; - to->addr_lo = from->addr_lo; /* already big endian */ - to->addr_hi = from->addr_hi; /* likewise */ - wmb(); - to->len_gen = cpu_to_be32(V_FLD_GEN1(q->gen)); - to->gen2 = cpu_to_be32(V_FLD_GEN2(q->gen)); - q->credits++; - - if (++q->pidx == q->size) { - q->pidx = 0; - q->gen ^= 1; - } - t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); -} - -/** - * alloc_ring - allocate resources for an SGE descriptor ring - * @pdev: the PCI device - * @nelem: the number of descriptors - * @elem_size: the size of each descriptor - * @sw_size: the size of the SW state associated with each ring element - * @phys: the physical address of the allocated ring - * @metadata: address of the array holding the SW state for the ring - * - * Allocates resources for an SGE descriptor ring, such as Tx queues, - * free buffer lists, or response queues. Each SGE ring requires - * space for its HW descriptors plus, optionally, space for the SW state - * associated with each HW entry (the metadata). The function returns - * three values: the virtual address for the HW ring (the return value - * of the function), the physical address of the HW ring, and the address - * of the SW ring. - */ -static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size, - size_t sw_size, dma_addr_t *phys, void *metadata) -{ - size_t len = nelem * elem_size; - void *s = NULL; - void *p = dma_alloc_coherent(&pdev->dev, len, phys, GFP_KERNEL); - - if (!p) - return NULL; - if (sw_size) { - s = kcalloc(nelem, sw_size, GFP_KERNEL); - - if (!s) { - dma_free_coherent(&pdev->dev, len, p, *phys); - return NULL; - } - } - if (metadata) - *(void **)metadata = s; - memset(p, 0, len); - return p; -} - -/** - * free_qset - free the resources of an SGE queue set - * @adapter: the adapter owning the queue set - * @q: the queue set - * - * Release the HW and SW resources associated with an SGE queue set, such - * as HW contexts, packet buffers, and descriptor rings. Traffic to the - * queue set must be quiesced prior to calling this. - */ -void t3_free_qset(struct adapter *adapter, struct sge_qset *q) -{ - int i; - struct pci_dev *pdev = adapter->pdev; - - if (q->tx_reclaim_timer.function) - del_timer_sync(&q->tx_reclaim_timer); - - for (i = 0; i < SGE_RXQ_PER_SET; ++i) - if (q->fl[i].desc) { - spin_lock(&adapter->sge.reg_lock); - t3_sge_disable_fl(adapter, q->fl[i].cntxt_id); - spin_unlock(&adapter->sge.reg_lock); - free_rx_bufs(pdev, &q->fl[i]); - kfree(q->fl[i].sdesc); - dma_free_coherent(&pdev->dev, - q->fl[i].size * - sizeof(struct rx_desc), q->fl[i].desc, - q->fl[i].phys_addr); - } - - for (i = 0; i < SGE_TXQ_PER_SET; ++i) - if (q->txq[i].desc) { - spin_lock(&adapter->sge.reg_lock); - t3_sge_enable_ecntxt(adapter, q->txq[i].cntxt_id, 0); - spin_unlock(&adapter->sge.reg_lock); - if (q->txq[i].sdesc) { - free_tx_desc(adapter, &q->txq[i], - q->txq[i].in_use); - kfree(q->txq[i].sdesc); - } - dma_free_coherent(&pdev->dev, - q->txq[i].size * - sizeof(struct tx_desc), - q->txq[i].desc, q->txq[i].phys_addr); - __skb_queue_purge(&q->txq[i].sendq); - } - - if (q->rspq.desc) { - spin_lock(&adapter->sge.reg_lock); - t3_sge_disable_rspcntxt(adapter, q->rspq.cntxt_id); - spin_unlock(&adapter->sge.reg_lock); - dma_free_coherent(&pdev->dev, - q->rspq.size * sizeof(struct rsp_desc), - q->rspq.desc, q->rspq.phys_addr); - } - - if (q->netdev) - q->netdev->atalk_ptr = NULL; - - memset(q, 0, sizeof(*q)); -} - -/** - * init_qset_cntxt - initialize an SGE queue set context info - * @qs: the queue set - * @id: the queue set id - * - * Initializes the TIDs and context ids for the queues of a queue set. - */ -static void init_qset_cntxt(struct sge_qset *qs, unsigned int id) -{ - qs->rspq.cntxt_id = id; - qs->fl[0].cntxt_id = 2 * id; - qs->fl[1].cntxt_id = 2 * id + 1; - qs->txq[TXQ_ETH].cntxt_id = FW_TUNNEL_SGEEC_START + id; - qs->txq[TXQ_ETH].token = FW_TUNNEL_TID_START + id; - qs->txq[TXQ_OFLD].cntxt_id = FW_OFLD_SGEEC_START + id; - qs->txq[TXQ_CTRL].cntxt_id = FW_CTRL_SGEEC_START + id; - qs->txq[TXQ_CTRL].token = FW_CTRL_TID_START + id; -} - -/** - * sgl_len - calculates the size of an SGL of the given capacity - * @n: the number of SGL entries - * - * Calculates the number of flits needed for a scatter/gather list that - * can hold the given number of entries. - */ -static inline unsigned int sgl_len(unsigned int n) -{ - /* alternatively: 3 * (n / 2) + 2 * (n & 1) */ - return (3 * n) / 2 + (n & 1); -} - -/** - * flits_to_desc - returns the num of Tx descriptors for the given flits - * @n: the number of flits - * - * Calculates the number of Tx descriptors needed for the supplied number - * of flits. - */ -static inline unsigned int flits_to_desc(unsigned int n) -{ - BUG_ON(n >= ARRAY_SIZE(flit_desc_map)); - return flit_desc_map[n]; -} - -/** - * get_packet - return the next ingress packet buffer from a free list - * @adap: the adapter that received the packet - * @fl: the SGE free list holding the packet - * @len: the packet length including any SGE padding - * @drop_thres: # of remaining buffers before we start dropping packets - * - * Get the next packet from a free list and complete setup of the - * sk_buff. If the packet is small we make a copy and recycle the - * original buffer, otherwise we use the original buffer itself. If a - * positive drop threshold is supplied packets are dropped and their - * buffers recycled if (a) the number of remaining buffers is under the - * threshold and the packet is too big to copy, or (b) the packet should - * be copied but there is no memory for the copy. - */ -static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl, - unsigned int len, unsigned int drop_thres) -{ - struct sk_buff *skb = NULL; - struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; - - prefetch(sd->skb->data); - - if (len <= SGE_RX_COPY_THRES) { - skb = alloc_skb(len, GFP_ATOMIC); - if (likely(skb != NULL)) { - __skb_put(skb, len); - pci_dma_sync_single_for_cpu(adap->pdev, - pci_unmap_addr(sd, - dma_addr), - len, PCI_DMA_FROMDEVICE); - memcpy(skb->data, sd->skb->data, len); - pci_dma_sync_single_for_device(adap->pdev, - pci_unmap_addr(sd, - dma_addr), - len, PCI_DMA_FROMDEVICE); - } else if (!drop_thres) - goto use_orig_buf; - recycle: - recycle_rx_buf(adap, fl, fl->cidx); - return skb; - } - - if (unlikely(fl->credits < drop_thres)) - goto recycle; - - use_orig_buf: - pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), - fl->buf_size, PCI_DMA_FROMDEVICE); - skb = sd->skb; - skb_put(skb, len); - __refill_fl(adap, fl); - return skb; -} - -/** - * get_imm_packet - return the next ingress packet buffer from a response - * @resp: the response descriptor containing the packet data - * - * Return a packet containing the immediate data of the given response. - */ -static inline struct sk_buff *get_imm_packet(const struct rsp_desc *resp) -{ - struct sk_buff *skb = alloc_skb(IMMED_PKT_SIZE, GFP_ATOMIC); - - if (skb) { - __skb_put(skb, IMMED_PKT_SIZE); - memcpy(skb->data, resp->imm_data, IMMED_PKT_SIZE); - } - return skb; -} - -/** - * calc_tx_descs - calculate the number of Tx descriptors for a packet - * @skb: the packet - * - * Returns the number of Tx descriptors needed for the given Ethernet - * packet. Ethernet packets require addition of WR and CPL headers. - */ -static inline unsigned int calc_tx_descs(const struct sk_buff *skb) -{ - unsigned int flits; - - if (skb->len <= WR_LEN - sizeof(struct cpl_tx_pkt)) - return 1; - - flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 2; - if (skb_shinfo(skb)->gso_size) - flits++; - return flits_to_desc(flits); -} - -/** - * make_sgl - populate a scatter/gather list for a packet - * @skb: the packet - * @sgp: the SGL to populate - * @start: start address of skb main body data to include in the SGL - * @len: length of skb main body data to include in the SGL - * @pdev: the PCI device - * - * Generates a scatter/gather list for the buffers that make up a packet - * and returns the SGL size in 8-byte words. The caller must size the SGL - * appropriately. - */ -static inline unsigned int make_sgl(const struct sk_buff *skb, - struct sg_ent *sgp, unsigned char *start, - unsigned int len, struct pci_dev *pdev) -{ - dma_addr_t mapping; - unsigned int i, j = 0, nfrags; - - if (len) { - mapping = pci_map_single(pdev, start, len, PCI_DMA_TODEVICE); - sgp->len[0] = cpu_to_be32(len); - sgp->addr[0] = cpu_to_be64(mapping); - j = 1; - } - - nfrags = skb_shinfo(skb)->nr_frags; - for (i = 0; i < nfrags; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - mapping = pci_map_page(pdev, frag->page, frag->page_offset, - frag->size, PCI_DMA_TODEVICE); - sgp->len[j] = cpu_to_be32(frag->size); - sgp->addr[j] = cpu_to_be64(mapping); - j ^= 1; - if (j == 0) - ++sgp; - } - if (j) - sgp->len[j] = 0; - return ((nfrags + (len != 0)) * 3) / 2 + j; -} - -/** - * check_ring_tx_db - check and potentially ring a Tx queue's doorbell - * @adap: the adapter - * @q: the Tx queue - * - * Ring the doorbel if a Tx queue is asleep. There is a natural race, - * where the HW is going to sleep just after we checked, however, - * then the interrupt handler will detect the outstanding TX packet - * and ring the doorbell for us. - * - * When GTS is disabled we unconditionally ring the doorbell. - */ -static inline void check_ring_tx_db(struct adapter *adap, struct sge_txq *q) -{ -#if USE_GTS - clear_bit(TXQ_LAST_PKT_DB, &q->flags); - if (test_and_set_bit(TXQ_RUNNING, &q->flags) == 0) { - set_bit(TXQ_LAST_PKT_DB, &q->flags); - t3_write_reg(adap, A_SG_KDOORBELL, - F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); - } -#else - wmb(); /* write descriptors before telling HW */ - t3_write_reg(adap, A_SG_KDOORBELL, - F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); -#endif -} - -static inline void wr_gen2(struct tx_desc *d, unsigned int gen) -{ -#if SGE_NUM_GENBITS == 2 - d->flit[TX_DESC_FLITS - 1] = cpu_to_be64(gen); -#endif -} - -/** - * write_wr_hdr_sgl - write a WR header and, optionally, SGL - * @ndesc: number of Tx descriptors spanned by the SGL - * @skb: the packet corresponding to the WR - * @d: first Tx descriptor to be written - * @pidx: index of above descriptors - * @q: the SGE Tx queue - * @sgl: the SGL - * @flits: number of flits to the start of the SGL in the first descriptor - * @sgl_flits: the SGL size in flits - * @gen: the Tx descriptor generation - * @wr_hi: top 32 bits of WR header based on WR type (big endian) - * @wr_lo: low 32 bits of WR header based on WR type (big endian) - * - * Write a work request header and an associated SGL. If the SGL is - * small enough to fit into one Tx descriptor it has already been written - * and we just need to write the WR header. Otherwise we distribute the - * SGL across the number of descriptors it spans. - */ -static void write_wr_hdr_sgl(unsigned int ndesc, struct sk_buff *skb, - struct tx_desc *d, unsigned int pidx, - const struct sge_txq *q, - const struct sg_ent *sgl, - unsigned int flits, unsigned int sgl_flits, - unsigned int gen, unsigned int wr_hi, - unsigned int wr_lo) -{ - struct work_request_hdr *wrp = (struct work_request_hdr *)d; - struct tx_sw_desc *sd = &q->sdesc[pidx]; - - sd->skb = skb; - if (need_skb_unmap()) { - struct unmap_info *ui = (struct unmap_info *)skb->cb; - - ui->fragidx = 0; - ui->addr_idx = 0; - ui->sflit = flits; - } - - if (likely(ndesc == 1)) { - skb->priority = pidx; - wrp->wr_hi = htonl(F_WR_SOP | F_WR_EOP | V_WR_DATATYPE(1) | - V_WR_SGLSFLT(flits)) | wr_hi; - wmb(); - wrp->wr_lo = htonl(V_WR_LEN(flits + sgl_flits) | - V_WR_GEN(gen)) | wr_lo; - wr_gen2(d, gen); - } else { - unsigned int ogen = gen; - const u64 *fp = (const u64 *)sgl; - struct work_request_hdr *wp = wrp; - - wrp->wr_hi = htonl(F_WR_SOP | V_WR_DATATYPE(1) | - V_WR_SGLSFLT(flits)) | wr_hi; - - while (sgl_flits) { - unsigned int avail = WR_FLITS - flits; - - if (avail > sgl_flits) - avail = sgl_flits; - memcpy(&d->flit[flits], fp, avail * sizeof(*fp)); - sgl_flits -= avail; - ndesc--; - if (!sgl_flits) - break; - - fp += avail; - d++; - sd++; - if (++pidx == q->size) { - pidx = 0; - gen ^= 1; - d = q->desc; - sd = q->sdesc; - } - - sd->skb = skb; - wrp = (struct work_request_hdr *)d; - wrp->wr_hi = htonl(V_WR_DATATYPE(1) | - V_WR_SGLSFLT(1)) | wr_hi; - wrp->wr_lo = htonl(V_WR_LEN(min(WR_FLITS, - sgl_flits + 1)) | - V_WR_GEN(gen)) | wr_lo; - wr_gen2(d, gen); - flits = 1; - } - skb->priority = pidx; - wrp->wr_hi |= htonl(F_WR_EOP); - wmb(); - wp->wr_lo = htonl(V_WR_LEN(WR_FLITS) | V_WR_GEN(ogen)) | wr_lo; - wr_gen2((struct tx_desc *)wp, ogen); - WARN_ON(ndesc != 0); - } -} - -/** - * write_tx_pkt_wr - write a TX_PKT work request - * @adap: the adapter - * @skb: the packet to send - * @pi: the egress interface - * @pidx: index of the first Tx descriptor to write - * @gen: the generation value to use - * @q: the Tx queue - * @ndesc: number of descriptors the packet will occupy - * @compl: the value of the COMPL bit to use - * - * Generate a TX_PKT work request to send the supplied packet. - */ -static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb, - const struct port_info *pi, - unsigned int pidx, unsigned int gen, - struct sge_txq *q, unsigned int ndesc, - unsigned int compl) -{ - unsigned int flits, sgl_flits, cntrl, tso_info; - struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1]; - struct tx_desc *d = &q->desc[pidx]; - struct cpl_tx_pkt *cpl = (struct cpl_tx_pkt *)d; - - cpl->len = htonl(skb->len | 0x80000000); - cntrl = V_TXPKT_INTF(pi->port_id); - - if (vlan_tx_tag_present(skb) && pi->vlan_grp) - cntrl |= F_TXPKT_VLAN_VLD | V_TXPKT_VLAN(vlan_tx_tag_get(skb)); - - tso_info = V_LSO_MSS(skb_shinfo(skb)->gso_size); - if (tso_info) { - int eth_type; - struct cpl_tx_pkt_lso *hdr = (struct cpl_tx_pkt_lso *)cpl; - - d->flit[2] = 0; - cntrl |= V_TXPKT_OPCODE(CPL_TX_PKT_LSO); - hdr->cntrl = htonl(cntrl); - eth_type = skb->nh.raw - skb->data == ETH_HLEN ? - CPL_ETH_II : CPL_ETH_II_VLAN; - tso_info |= V_LSO_ETH_TYPE(eth_type) | - V_LSO_IPHDR_WORDS(skb->nh.iph->ihl) | - V_LSO_TCPHDR_WORDS(skb->h.th->doff); - hdr->lso_info = htonl(tso_info); - flits = 3; - } else { - cntrl |= V_TXPKT_OPCODE(CPL_TX_PKT); - cntrl |= F_TXPKT_IPCSUM_DIS; /* SW calculates IP csum */ - cntrl |= V_TXPKT_L4CSUM_DIS(skb->ip_summed != CHECKSUM_PARTIAL); - cpl->cntrl = htonl(cntrl); - - if (skb->len <= WR_LEN - sizeof(*cpl)) { - q->sdesc[pidx].skb = NULL; - if (!skb->data_len) - memcpy(&d->flit[2], skb->data, skb->len); - else - skb_copy_bits(skb, 0, &d->flit[2], skb->len); - - flits = (skb->len + 7) / 8 + 2; - cpl->wr.wr_hi = htonl(V_WR_BCNTLFLT(skb->len & 7) | - V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) - | F_WR_SOP | F_WR_EOP | compl); - wmb(); - cpl->wr.wr_lo = htonl(V_WR_LEN(flits) | V_WR_GEN(gen) | - V_WR_TID(q->token)); - wr_gen2(d, gen); - kfree_skb(skb); - return; - } - - flits = 2; - } - - sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; - sgl_flits = make_sgl(skb, sgp, skb->data, skb_headlen(skb), adap->pdev); - if (need_skb_unmap()) - ((struct unmap_info *)skb->cb)->len = skb_headlen(skb); - - write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen, - htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl), - htonl(V_WR_TID(q->token))); -} - -/** - * eth_xmit - add a packet to the Ethernet Tx queue - * @skb: the packet - * @dev: the egress net device - * - * Add a packet to an SGE Tx queue. Runs with softirqs disabled. - */ -int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned int ndesc, pidx, credits, gen, compl; - const struct port_info *pi = netdev_priv(dev); - struct adapter *adap = dev->priv; - struct sge_qset *qs = dev2qset(dev); - struct sge_txq *q = &qs->txq[TXQ_ETH]; - - /* - * The chip min packet length is 9 octets but play safe and reject - * anything shorter than an Ethernet header. - */ - if (unlikely(skb->len < ETH_HLEN)) { - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - spin_lock(&q->lock); - reclaim_completed_tx(adap, q); - - credits = q->size - q->in_use; - ndesc = calc_tx_descs(skb); - - if (unlikely(credits < ndesc)) { - if (!netif_queue_stopped(dev)) { - netif_stop_queue(dev); - set_bit(TXQ_ETH, &qs->txq_stopped); - q->stops++; - dev_err(&adap->pdev->dev, - "%s: Tx ring %u full while queue awake!\n", - dev->name, q->cntxt_id & 7); - } - spin_unlock(&q->lock); - return NETDEV_TX_BUSY; - } - - q->in_use += ndesc; - if (unlikely(credits - ndesc < q->stop_thres)) { - q->stops++; - netif_stop_queue(dev); - set_bit(TXQ_ETH, &qs->txq_stopped); -#if !USE_GTS - if (should_restart_tx(q) && - test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) { - q->restarts++; - netif_wake_queue(dev); - } -#endif - } - - gen = q->gen; - q->unacked += ndesc; - compl = (q->unacked & 8) << (S_WR_COMPL - 3); - q->unacked &= 7; - pidx = q->pidx; - q->pidx += ndesc; - if (q->pidx >= q->size) { - q->pidx -= q->size; - q->gen ^= 1; - } - - /* update port statistics */ - if (skb->ip_summed == CHECKSUM_COMPLETE) - qs->port_stats[SGE_PSTAT_TX_CSUM]++; - if (skb_shinfo(skb)->gso_size) - qs->port_stats[SGE_PSTAT_TSO]++; - if (vlan_tx_tag_present(skb) && pi->vlan_grp) - qs->port_stats[SGE_PSTAT_VLANINS]++; - - dev->trans_start = jiffies; - spin_unlock(&q->lock); - - /* - * We do not use Tx completion interrupts to free DMAd Tx packets. - * This is good for performamce but means that we rely on new Tx - * packets arriving to run the destructors of completed packets, - * which open up space in their sockets' send queues. Sometimes - * we do not get such new packets causing Tx to stall. A single - * UDP transmitter is a good example of this situation. We have - * a clean up timer that periodically reclaims completed packets - * but it doesn't run often enough (nor do we want it to) to prevent - * lengthy stalls. A solution to this problem is to run the - * destructor early, after the packet is queued but before it's DMAd. - * A cons is that we lie to socket memory accounting, but the amount - * of extra memory is reasonable (limited by the number of Tx - * descriptors), the packets do actually get freed quickly by new - * packets almost always, and for protocols like TCP that wait for - * acks to really free up the data the extra memory is even less. - * On the positive side we run the destructors on the sending CPU - * rather than on a potentially different completing CPU, usually a - * good thing. We also run them without holding our Tx queue lock, - * unlike what reclaim_completed_tx() would otherwise do. - * - * Run the destructor before telling the DMA engine about the packet - * to make sure it doesn't complete and get freed prematurely. - */ - if (likely(!skb_shared(skb))) - skb_orphan(skb); - - write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl); - check_ring_tx_db(adap, q); - return NETDEV_TX_OK; -} - -/** - * write_imm - write a packet into a Tx descriptor as immediate data - * @d: the Tx descriptor to write - * @skb: the packet - * @len: the length of packet data to write as immediate data - * @gen: the generation bit value to write - * - * Writes a packet as immediate data into a Tx descriptor. The packet - * contains a work request at its beginning. We must write the packet - * carefully so the SGE doesn't read accidentally before it's written in - * its entirety. - */ -static inline void write_imm(struct tx_desc *d, struct sk_buff *skb, - unsigned int len, unsigned int gen) -{ - struct work_request_hdr *from = (struct work_request_hdr *)skb->data; - struct work_request_hdr *to = (struct work_request_hdr *)d; - - memcpy(&to[1], &from[1], len - sizeof(*from)); - to->wr_hi = from->wr_hi | htonl(F_WR_SOP | F_WR_EOP | - V_WR_BCNTLFLT(len & 7)); - wmb(); - to->wr_lo = from->wr_lo | htonl(V_WR_GEN(gen) | - V_WR_LEN((len + 7) / 8)); - wr_gen2(d, gen); - kfree_skb(skb); -} - -/** - * check_desc_avail - check descriptor availability on a send queue - * @adap: the adapter - * @q: the send queue - * @skb: the packet needing the descriptors - * @ndesc: the number of Tx descriptors needed - * @qid: the Tx queue number in its queue set (TXQ_OFLD or TXQ_CTRL) - * - * Checks if the requested number of Tx descriptors is available on an - * SGE send queue. If the queue is already suspended or not enough - * descriptors are available the packet is queued for later transmission. - * Must be called with the Tx queue locked. - * - * Returns 0 if enough descriptors are available, 1 if there aren't - * enough descriptors and the packet has been queued, and 2 if the caller - * needs to retry because there weren't enough descriptors at the - * beginning of the call but some freed up in the mean time. - */ -static inline int check_desc_avail(struct adapter *adap, struct sge_txq *q, - struct sk_buff *skb, unsigned int ndesc, - unsigned int qid) -{ - if (unlikely(!skb_queue_empty(&q->sendq))) { - addq_exit:__skb_queue_tail(&q->sendq, skb); - return 1; - } - if (unlikely(q->size - q->in_use < ndesc)) { - struct sge_qset *qs = txq_to_qset(q, qid); - - set_bit(qid, &qs->txq_stopped); - smp_mb__after_clear_bit(); - - if (should_restart_tx(q) && - test_and_clear_bit(qid, &qs->txq_stopped)) - return 2; - - q->stops++; - goto addq_exit; - } - return 0; -} - -/** - * reclaim_completed_tx_imm - reclaim completed control-queue Tx descs - * @q: the SGE control Tx queue - * - * This is a variant of reclaim_completed_tx() that is used for Tx queues - * that send only immediate data (presently just the control queues) and - * thus do not have any sk_buffs to release. - */ -static inline void reclaim_completed_tx_imm(struct sge_txq *q) -{ - unsigned int reclaim = q->processed - q->cleaned; - - q->in_use -= reclaim; - q->cleaned += reclaim; -} - -static inline int immediate(const struct sk_buff *skb) -{ - return skb->len <= WR_LEN && !skb->data_len; -} - -/** - * ctrl_xmit - send a packet through an SGE control Tx queue - * @adap: the adapter - * @q: the control queue - * @skb: the packet - * - * Send a packet through an SGE control Tx queue. Packets sent through - * a control queue must fit entirely as immediate data in a single Tx - * descriptor and have no page fragments. - */ -static int ctrl_xmit(struct adapter *adap, struct sge_txq *q, - struct sk_buff *skb) -{ - int ret; - struct work_request_hdr *wrp = (struct work_request_hdr *)skb->data; - - if (unlikely(!immediate(skb))) { - WARN_ON(1); - dev_kfree_skb(skb); - return NET_XMIT_SUCCESS; - } - - wrp->wr_hi |= htonl(F_WR_SOP | F_WR_EOP); - wrp->wr_lo = htonl(V_WR_TID(q->token)); - - spin_lock(&q->lock); - again:reclaim_completed_tx_imm(q); - - ret = check_desc_avail(adap, q, skb, 1, TXQ_CTRL); - if (unlikely(ret)) { - if (ret == 1) { - spin_unlock(&q->lock); - return NET_XMIT_CN; - } - goto again; - } - - write_imm(&q->desc[q->pidx], skb, skb->len, q->gen); - - q->in_use++; - if (++q->pidx >= q->size) { - q->pidx = 0; - q->gen ^= 1; - } - spin_unlock(&q->lock); - wmb(); - t3_write_reg(adap, A_SG_KDOORBELL, - F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); - return NET_XMIT_SUCCESS; -} - -/** - * restart_ctrlq - restart a suspended control queue - * @qs: the queue set cotaining the control queue - * - * Resumes transmission on a suspended Tx control queue. - */ -static void restart_ctrlq(unsigned long data) -{ - struct sk_buff *skb; - struct sge_qset *qs = (struct sge_qset *)data; - struct sge_txq *q = &qs->txq[TXQ_CTRL]; - struct adapter *adap = qs->netdev->priv; - - spin_lock(&q->lock); - again:reclaim_completed_tx_imm(q); - - while (q->in_use < q->size && (skb = __skb_dequeue(&q->sendq)) != NULL) { - - write_imm(&q->desc[q->pidx], skb, skb->len, q->gen); - - if (++q->pidx >= q->size) { - q->pidx = 0; - q->gen ^= 1; - } - q->in_use++; - } - - if (!skb_queue_empty(&q->sendq)) { - set_bit(TXQ_CTRL, &qs->txq_stopped); - smp_mb__after_clear_bit(); - - if (should_restart_tx(q) && - test_and_clear_bit(TXQ_CTRL, &qs->txq_stopped)) - goto again; - q->stops++; - } - - spin_unlock(&q->lock); - t3_write_reg(adap, A_SG_KDOORBELL, - F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); -} - -/* - * Send a management message through control queue 0 - */ -int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb) -{ - return ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb); -} - -/** - * write_ofld_wr - write an offload work request - * @adap: the adapter - * @skb: the packet to send - * @q: the Tx queue - * @pidx: index of the first Tx descriptor to write - * @gen: the generation value to use - * @ndesc: number of descriptors the packet will occupy - * - * Write an offload work request to send the supplied packet. The packet - * data already carry the work request with most fields populated. - */ -static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb, - struct sge_txq *q, unsigned int pidx, - unsigned int gen, unsigned int ndesc) -{ - unsigned int sgl_flits, flits; - struct work_request_hdr *from; - struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1]; - struct tx_desc *d = &q->desc[pidx]; - - if (immediate(skb)) { - q->sdesc[pidx].skb = NULL; - write_imm(d, skb, skb->len, gen); - return; - } - - /* Only TX_DATA builds SGLs */ - - from = (struct work_request_hdr *)skb->data; - memcpy(&d->flit[1], &from[1], skb->h.raw - skb->data - sizeof(*from)); - - flits = (skb->h.raw - skb->data) / 8; - sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; - sgl_flits = make_sgl(skb, sgp, skb->h.raw, skb->tail - skb->h.raw, - adap->pdev); - if (need_skb_unmap()) - ((struct unmap_info *)skb->cb)->len = skb->tail - skb->h.raw; - - write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, - gen, from->wr_hi, from->wr_lo); -} - -/** - * calc_tx_descs_ofld - calculate # of Tx descriptors for an offload packet - * @skb: the packet - * - * Returns the number of Tx descriptors needed for the given offload - * packet. These packets are already fully constructed. - */ -static inline unsigned int calc_tx_descs_ofld(const struct sk_buff *skb) -{ - unsigned int flits, cnt = skb_shinfo(skb)->nr_frags; - - if (skb->len <= WR_LEN && cnt == 0) - return 1; /* packet fits as immediate data */ - - flits = (skb->h.raw - skb->data) / 8; /* headers */ - if (skb->tail != skb->h.raw) - cnt++; - return flits_to_desc(flits + sgl_len(cnt)); -} - -/** - * ofld_xmit - send a packet through an offload queue - * @adap: the adapter - * @q: the Tx offload queue - * @skb: the packet - * - * Send an offload packet through an SGE offload queue. - */ -static int ofld_xmit(struct adapter *adap, struct sge_txq *q, - struct sk_buff *skb) -{ - int ret; - unsigned int ndesc = calc_tx_descs_ofld(skb), pidx, gen; - - spin_lock(&q->lock); - again:reclaim_completed_tx(adap, q); - - ret = check_desc_avail(adap, q, skb, ndesc, TXQ_OFLD); - if (unlikely(ret)) { - if (ret == 1) { - skb->priority = ndesc; /* save for restart */ - spin_unlock(&q->lock); - return NET_XMIT_CN; - } - goto again; - } - - gen = q->gen; - q->in_use += ndesc; - pidx = q->pidx; - q->pidx += ndesc; - if (q->pidx >= q->size) { - q->pidx -= q->size; - q->gen ^= 1; - } - spin_unlock(&q->lock); - - write_ofld_wr(adap, skb, q, pidx, gen, ndesc); - check_ring_tx_db(adap, q); - return NET_XMIT_SUCCESS; -} - -/** - * restart_offloadq - restart a suspended offload queue - * @qs: the queue set cotaining the offload queue - * - * Resumes transmission on a suspended Tx offload queue. - */ -static void restart_offloadq(unsigned long data) -{ - struct sk_buff *skb; - struct sge_qset *qs = (struct sge_qset *)data; - struct sge_txq *q = &qs->txq[TXQ_OFLD]; - struct adapter *adap = qs->netdev->priv; - - spin_lock(&q->lock); - again:reclaim_completed_tx(adap, q); - - while ((skb = skb_peek(&q->sendq)) != NULL) { - unsigned int gen, pidx; - unsigned int ndesc = skb->priority; - - if (unlikely(q->size - q->in_use < ndesc)) { - set_bit(TXQ_OFLD, &qs->txq_stopped); - smp_mb__after_clear_bit(); - - if (should_restart_tx(q) && - test_and_clear_bit(TXQ_OFLD, &qs->txq_stopped)) - goto again; - q->stops++; - break; - } - - gen = q->gen; - q->in_use += ndesc; - pidx = q->pidx; - q->pidx += ndesc; - if (q->pidx >= q->size) { - q->pidx -= q->size; - q->gen ^= 1; - } - __skb_unlink(skb, &q->sendq); - spin_unlock(&q->lock); - - write_ofld_wr(adap, skb, q, pidx, gen, ndesc); - spin_lock(&q->lock); - } - spin_unlock(&q->lock); - -#if USE_GTS - set_bit(TXQ_RUNNING, &q->flags); - set_bit(TXQ_LAST_PKT_DB, &q->flags); -#endif - t3_write_reg(adap, A_SG_KDOORBELL, - F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); -} - -/** - * queue_set - return the queue set a packet should use - * @skb: the packet - * - * Maps a packet to the SGE queue set it should use. The desired queue - * set is carried in bits 1-3 in the packet's priority. - */ -static inline int queue_set(const struct sk_buff *skb) -{ - return skb->priority >> 1; -} - -/** - * is_ctrl_pkt - return whether an offload packet is a control packet - * @skb: the packet - * - * Determines whether an offload packet should use an OFLD or a CTRL - * Tx queue. This is indicated by bit 0 in the packet's priority. - */ -static inline int is_ctrl_pkt(const struct sk_buff *skb) -{ - return skb->priority & 1; -} - -/** - * t3_offload_tx - send an offload packet - * @tdev: the offload device to send to - * @skb: the packet - * - * Sends an offload packet. We use the packet priority to select the - * appropriate Tx queue as follows: bit 0 indicates whether the packet - * should be sent as regular or control, bits 1-3 select the queue set. - */ -int t3_offload_tx(struct t3cdev *tdev, struct sk_buff *skb) -{ - struct adapter *adap = tdev2adap(tdev); - struct sge_qset *qs = &adap->sge.qs[queue_set(skb)]; - - if (unlikely(is_ctrl_pkt(skb))) - return ctrl_xmit(adap, &qs->txq[TXQ_CTRL], skb); - - return ofld_xmit(adap, &qs->txq[TXQ_OFLD], skb); -} - -/** - * offload_enqueue - add an offload packet to an SGE offload receive queue - * @q: the SGE response queue - * @skb: the packet - * - * Add a new offload packet to an SGE response queue's offload packet - * queue. If the packet is the first on the queue it schedules the RX - * softirq to process the queue. - */ -static inline void offload_enqueue(struct sge_rspq *q, struct sk_buff *skb) -{ - skb->next = skb->prev = NULL; - if (q->rx_tail) - q->rx_tail->next = skb; - else { - struct sge_qset *qs = rspq_to_qset(q); - - if (__netif_rx_schedule_prep(qs->netdev)) - __netif_rx_schedule(qs->netdev); - q->rx_head = skb; - } - q->rx_tail = skb; -} - -/** - * deliver_partial_bundle - deliver a (partial) bundle of Rx offload pkts - * @tdev: the offload device that will be receiving the packets - * @q: the SGE response queue that assembled the bundle - * @skbs: the partial bundle - * @n: the number of packets in the bundle - * - * Delivers a (partial) bundle of Rx offload packets to an offload device. - */ -static inline void deliver_partial_bundle(struct t3cdev *tdev, - struct sge_rspq *q, - struct sk_buff *skbs[], int n) -{ - if (n) { - q->offload_bundles++; - tdev->recv(tdev, skbs, n); - } -} - -/** - * ofld_poll - NAPI handler for offload packets in interrupt mode - * @dev: the network device doing the polling - * @budget: polling budget - * - * The NAPI handler for offload packets when a response queue is serviced - * by the hard interrupt handler, i.e., when it's operating in non-polling - * mode. Creates small packet batches and sends them through the offload - * receive handler. Batches need to be of modest size as we do prefetches - * on the packets in each. - */ -static int ofld_poll(struct net_device *dev, int *budget) -{ - struct adapter *adapter = dev->priv; - struct sge_qset *qs = dev2qset(dev); - struct sge_rspq *q = &qs->rspq; - int work_done, limit = min(*budget, dev->quota), avail = limit; - - while (avail) { - struct sk_buff *head, *tail, *skbs[RX_BUNDLE_SIZE]; - int ngathered; - - spin_lock_irq(&q->lock); - head = q->rx_head; - if (!head) { - work_done = limit - avail; - *budget -= work_done; - dev->quota -= work_done; - __netif_rx_complete(dev); - spin_unlock_irq(&q->lock); - return 0; - } - - tail = q->rx_tail; - q->rx_head = q->rx_tail = NULL; - spin_unlock_irq(&q->lock); - - for (ngathered = 0; avail && head; avail--) { - prefetch(head->data); - skbs[ngathered] = head; - head = head->next; - skbs[ngathered]->next = NULL; - if (++ngathered == RX_BUNDLE_SIZE) { - q->offload_bundles++; - adapter->tdev.recv(&adapter->tdev, skbs, - ngathered); - ngathered = 0; - } - } - if (head) { /* splice remaining packets back onto Rx queue */ - spin_lock_irq(&q->lock); - tail->next = q->rx_head; - if (!q->rx_head) - q->rx_tail = tail; - q->rx_head = head; - spin_unlock_irq(&q->lock); - } - deliver_partial_bundle(&adapter->tdev, q, skbs, ngathered); - } - work_done = limit - avail; - *budget -= work_done; - dev->quota -= work_done; - return 1; -} - -/** - * rx_offload - process a received offload packet - * @tdev: the offload device receiving the packet - * @rq: the response queue that received the packet - * @skb: the packet - * @rx_gather: a gather list of packets if we are building a bundle - * @gather_idx: index of the next available slot in the bundle - * - * Process an ingress offload pakcet and add it to the offload ingress - * queue. Returns the index of the next available slot in the bundle. - */ -static inline int rx_offload(struct t3cdev *tdev, struct sge_rspq *rq, - struct sk_buff *skb, struct sk_buff *rx_gather[], - unsigned int gather_idx) -{ - rq->offload_pkts++; - skb->mac.raw = skb->nh.raw = skb->h.raw = skb->data; - - if (rq->polling) { - rx_gather[gather_idx++] = skb; - if (gather_idx == RX_BUNDLE_SIZE) { - tdev->recv(tdev, rx_gather, RX_BUNDLE_SIZE); - gather_idx = 0; - rq->offload_bundles++; - } - } else - offload_enqueue(rq, skb); - - return gather_idx; -} - -/** - * restart_tx - check whether to restart suspended Tx queues - * @qs: the queue set to resume - * - * Restarts suspended Tx queues of an SGE queue set if they have enough - * free resources to resume operation. - */ -static void restart_tx(struct sge_qset *qs) -{ - if (test_bit(TXQ_ETH, &qs->txq_stopped) && - should_restart_tx(&qs->txq[TXQ_ETH]) && - test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) { - qs->txq[TXQ_ETH].restarts++; - if (netif_running(qs->netdev)) - netif_wake_queue(qs->netdev); - } - - if (test_bit(TXQ_OFLD, &qs->txq_stopped) && - should_restart_tx(&qs->txq[TXQ_OFLD]) && - test_and_clear_bit(TXQ_OFLD, &qs->txq_stopped)) { - qs->txq[TXQ_OFLD].restarts++; - tasklet_schedule(&qs->txq[TXQ_OFLD].qresume_tsk); - } - if (test_bit(TXQ_CTRL, &qs->txq_stopped) && - should_restart_tx(&qs->txq[TXQ_CTRL]) && - test_and_clear_bit(TXQ_CTRL, &qs->txq_stopped)) { - qs->txq[TXQ_CTRL].restarts++; - tasklet_schedule(&qs->txq[TXQ_CTRL].qresume_tsk); - } -} - -/** - * rx_eth - process an ingress ethernet packet - * @adap: the adapter - * @rq: the response queue that received the packet - * @skb: the packet - * @pad: amount of padding at the start of the buffer - * - * Process an ingress ethernet pakcet and deliver it to the stack. - * The padding is 2 if the packet was delivered in an Rx buffer and 0 - * if it was immediate data in a response. - */ -static void rx_eth(struct adapter *adap, struct sge_rspq *rq, - struct sk_buff *skb, int pad) -{ - struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad); - struct port_info *pi; - - rq->eth_pkts++; - skb_pull(skb, sizeof(*p) + pad); - skb->dev = adap->port[p->iff]; - skb->dev->last_rx = jiffies; - skb->protocol = eth_type_trans(skb, skb->dev); - pi = netdev_priv(skb->dev); - if (pi->rx_csum_offload && p->csum_valid && p->csum == 0xffff && - !p->fragment) { - rspq_to_qset(rq)->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++; - skb->ip_summed = CHECKSUM_UNNECESSARY; - } else - skb->ip_summed = CHECKSUM_NONE; - - if (unlikely(p->vlan_valid)) { - struct vlan_group *grp = pi->vlan_grp; - - rspq_to_qset(rq)->port_stats[SGE_PSTAT_VLANEX]++; - if (likely(grp)) - __vlan_hwaccel_rx(skb, grp, ntohs(p->vlan), - rq->polling); - else - dev_kfree_skb_any(skb); - } else if (rq->polling) - netif_receive_skb(skb); - else - netif_rx(skb); -} - -/** - * handle_rsp_cntrl_info - handles control information in a response - * @qs: the queue set corresponding to the response - * @flags: the response control flags - * - * Handles the control information of an SGE response, such as GTS - * indications and completion credits for the queue set's Tx queues. - * HW coalesces credits, we don't do any extra SW coalescing. - */ -static inline void handle_rsp_cntrl_info(struct sge_qset *qs, u32 flags) -{ - unsigned int credits; - -#if USE_GTS - if (flags & F_RSPD_TXQ0_GTS) - clear_bit(TXQ_RUNNING, &qs->txq[TXQ_ETH].flags); -#endif - - credits = G_RSPD_TXQ0_CR(flags); - if (credits) - qs->txq[TXQ_ETH].processed += credits; - - credits = G_RSPD_TXQ2_CR(flags); - if (credits) - qs->txq[TXQ_CTRL].processed += credits; - -# if USE_GTS - if (flags & F_RSPD_TXQ1_GTS) - clear_bit(TXQ_RUNNING, &qs->txq[TXQ_OFLD].flags); -# endif - credits = G_RSPD_TXQ1_CR(flags); - if (credits) - qs->txq[TXQ_OFLD].processed += credits; -} - -/** - * check_ring_db - check if we need to ring any doorbells - * @adapter: the adapter - * @qs: the queue set whose Tx queues are to be examined - * @sleeping: indicates which Tx queue sent GTS - * - * Checks if some of a queue set's Tx queues need to ring their doorbells - * to resume transmission after idling while they still have unprocessed - * descriptors. - */ -static void check_ring_db(struct adapter *adap, struct sge_qset *qs, - unsigned int sleeping) -{ - if (sleeping & F_RSPD_TXQ0_GTS) { - struct sge_txq *txq = &qs->txq[TXQ_ETH]; - - if (txq->cleaned + txq->in_use != txq->processed && - !test_and_set_bit(TXQ_LAST_PKT_DB, &txq->flags)) { - set_bit(TXQ_RUNNING, &txq->flags); - t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX | - V_EGRCNTX(txq->cntxt_id)); - } - } - - if (sleeping & F_RSPD_TXQ1_GTS) { - struct sge_txq *txq = &qs->txq[TXQ_OFLD]; - - if (txq->cleaned + txq->in_use != txq->processed && - !test_and_set_bit(TXQ_LAST_PKT_DB, &txq->flags)) { - set_bit(TXQ_RUNNING, &txq->flags); - t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX | - V_EGRCNTX(txq->cntxt_id)); - } - } -} - -/** - * is_new_response - check if a response is newly written - * @r: the response descriptor - * @q: the response queue - * - * Returns true if a response descriptor contains a yet unprocessed - * response. - */ -static inline int is_new_response(const struct rsp_desc *r, - const struct sge_rspq *q) -{ - return (r->intr_gen & F_RSPD_GEN2) == q->gen; -} - -#define RSPD_GTS_MASK (F_RSPD_TXQ0_GTS | F_RSPD_TXQ1_GTS) -#define RSPD_CTRL_MASK (RSPD_GTS_MASK | \ - V_RSPD_TXQ0_CR(M_RSPD_TXQ0_CR) | \ - V_RSPD_TXQ1_CR(M_RSPD_TXQ1_CR) | \ - V_RSPD_TXQ2_CR(M_RSPD_TXQ2_CR)) - -/* How long to delay the next interrupt in case of memory shortage, in 0.1us. */ -#define NOMEM_INTR_DELAY 2500 - -/** - * process_responses - process responses from an SGE response queue - * @adap: the adapter - * @qs: the queue set to which the response queue belongs - * @budget: how many responses can be processed in this round - * - * Process responses from an SGE response queue up to the supplied budget. - * Responses include received packets as well as credits and other events - * for the queues that belong to the response queue's queue set. - * A negative budget is effectively unlimited. - * - * Additionally choose the interrupt holdoff time for the next interrupt - * on this queue. If the system is under memory shortage use a fairly - * long delay to help recovery. - */ -static int process_responses(struct adapter *adap, struct sge_qset *qs, - int budget) -{ - struct sge_rspq *q = &qs->rspq; - struct rsp_desc *r = &q->desc[q->cidx]; - int budget_left = budget; - unsigned int sleeping = 0; - struct sk_buff *offload_skbs[RX_BUNDLE_SIZE]; - int ngathered = 0; - - q->next_holdoff = q->holdoff_tmr; - - while (likely(budget_left && is_new_response(r, q))) { - int eth, ethpad = 0; - struct sk_buff *skb = NULL; - u32 len, flags = ntohl(r->flags); - u32 rss_hi = *(const u32 *)r, rss_lo = r->rss_hdr.rss_hash_val; - - eth = r->rss_hdr.opcode == CPL_RX_PKT; - - if (unlikely(flags & F_RSPD_ASYNC_NOTIF)) { - skb = alloc_skb(AN_PKT_SIZE, GFP_ATOMIC); - if (!skb) - goto no_mem; - - memcpy(__skb_put(skb, AN_PKT_SIZE), r, AN_PKT_SIZE); - skb->data[0] = CPL_ASYNC_NOTIF; - rss_hi = htonl(CPL_ASYNC_NOTIF << 24); - q->async_notif++; - } else if (flags & F_RSPD_IMM_DATA_VALID) { - skb = get_imm_packet(r); - if (unlikely(!skb)) { - no_mem: - q->next_holdoff = NOMEM_INTR_DELAY; - q->nomem++; - /* consume one credit since we tried */ - budget_left--; - break; - } - q->imm_data++; - } else if ((len = ntohl(r->len_cq)) != 0) { - struct sge_fl *fl; - - fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; - fl->credits--; - skb = get_packet(adap, fl, G_RSPD_LEN(len), - eth ? SGE_RX_DROP_THRES : 0); - if (!skb) - q->rx_drops++; - else if (r->rss_hdr.opcode == CPL_TRACE_PKT) - __skb_pull(skb, 2); - ethpad = 2; - if (++fl->cidx == fl->size) - fl->cidx = 0; - } else - q->pure_rsps++; - - if (flags & RSPD_CTRL_MASK) { - sleeping |= flags & RSPD_GTS_MASK; - handle_rsp_cntrl_info(qs, flags); - } - - r++; - if (unlikely(++q->cidx == q->size)) { - q->cidx = 0; - q->gen ^= 1; - r = q->desc; - } - prefetch(r); - - if (++q->credits >= (q->size / 4)) { - refill_rspq(adap, q, q->credits); - q->credits = 0; - } - - if (likely(skb != NULL)) { - if (eth) - rx_eth(adap, q, skb, ethpad); - else { - /* Preserve the RSS info in csum & priority */ - skb->csum = rss_hi; - skb->priority = rss_lo; - ngathered = rx_offload(&adap->tdev, q, skb, - offload_skbs, ngathered); - } - } - - --budget_left; - } - - deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered); - if (sleeping) - check_ring_db(adap, qs, sleeping); - - smp_mb(); /* commit Tx queue .processed updates */ - if (unlikely(qs->txq_stopped != 0)) - restart_tx(qs); - - budget -= budget_left; - return budget; -} - -static inline int is_pure_response(const struct rsp_desc *r) -{ - u32 n = ntohl(r->flags) & (F_RSPD_ASYNC_NOTIF | F_RSPD_IMM_DATA_VALID); - - return (n | r->len_cq) == 0; -} - -/** - * napi_rx_handler - the NAPI handler for Rx processing - * @dev: the net device - * @budget: how many packets we can process in this round - * - * Handler for new data events when using NAPI. - */ -static int napi_rx_handler(struct net_device *dev, int *budget) -{ - struct adapter *adap = dev->priv; - struct sge_qset *qs = dev2qset(dev); - int effective_budget = min(*budget, dev->quota); - - int work_done = process_responses(adap, qs, effective_budget); - *budget -= work_done; - dev->quota -= work_done; - - if (work_done >= effective_budget) - return 1; - - netif_rx_complete(dev); - - /* - * Because we don't atomically flush the following write it is - * possible that in very rare cases it can reach the device in a way - * that races with a new response being written plus an error interrupt - * causing the NAPI interrupt handler below to return unhandled status - * to the OS. To protect against this would require flushing the write - * and doing both the write and the flush with interrupts off. Way too - * expensive and unjustifiable given the rarity of the race. - * - * The race cannot happen at all with MSI-X. - */ - t3_write_reg(adap, A_SG_GTS, V_RSPQ(qs->rspq.cntxt_id) | - V_NEWTIMER(qs->rspq.next_holdoff) | - V_NEWINDEX(qs->rspq.cidx)); - return 0; -} - -/* - * Returns true if the device is already scheduled for polling. - */ -static inline int napi_is_scheduled(struct net_device *dev) -{ - return test_bit(__LINK_STATE_RX_SCHED, &dev->state); -} - -/** - * process_pure_responses - process pure responses from a response queue - * @adap: the adapter - * @qs: the queue set owning the response queue - * @r: the first pure response to process - * - * A simpler version of process_responses() that handles only pure (i.e., - * non data-carrying) responses. Such respones are too light-weight to - * justify calling a softirq under NAPI, so we handle them specially in - * the interrupt handler. The function is called with a pointer to a - * response, which the caller must ensure is a valid pure response. - * - * Returns 1 if it encounters a valid data-carrying response, 0 otherwise. - */ -static int process_pure_responses(struct adapter *adap, struct sge_qset *qs, - struct rsp_desc *r) -{ - struct sge_rspq *q = &qs->rspq; - unsigned int sleeping = 0; - - do { - u32 flags = ntohl(r->flags); - - r++; - if (unlikely(++q->cidx == q->size)) { - q->cidx = 0; - q->gen ^= 1; - r = q->desc; - } - prefetch(r); - - if (flags & RSPD_CTRL_MASK) { - sleeping |= flags & RSPD_GTS_MASK; - handle_rsp_cntrl_info(qs, flags); - } - - q->pure_rsps++; - if (++q->credits >= (q->size / 4)) { - refill_rspq(adap, q, q->credits); - q->credits = 0; - } - } while (is_new_response(r, q) && is_pure_response(r)); - - if (sleeping) - check_ring_db(adap, qs, sleeping); - - smp_mb(); /* commit Tx queue .processed updates */ - if (unlikely(qs->txq_stopped != 0)) - restart_tx(qs); - - return is_new_response(r, q); -} - -/** - * handle_responses - decide what to do with new responses in NAPI mode - * @adap: the adapter - * @q: the response queue - * - * This is used by the NAPI interrupt handlers to decide what to do with - * new SGE responses. If there are no new responses it returns -1. If - * there are new responses and they are pure (i.e., non-data carrying) - * it handles them straight in hard interrupt context as they are very - * cheap and don't deliver any packets. Finally, if there are any data - * signaling responses it schedules the NAPI handler. Returns 1 if it - * schedules NAPI, 0 if all new responses were pure. - * - * The caller must ascertain NAPI is not already running. - */ -static inline int handle_responses(struct adapter *adap, struct sge_rspq *q) -{ - struct sge_qset *qs = rspq_to_qset(q); - struct rsp_desc *r = &q->desc[q->cidx]; - - if (!is_new_response(r, q)) - return -1; - if (is_pure_response(r) && process_pure_responses(adap, qs, r) == 0) { - t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) | - V_NEWTIMER(q->holdoff_tmr) | V_NEWINDEX(q->cidx)); - return 0; - } - if (likely(__netif_rx_schedule_prep(qs->netdev))) - __netif_rx_schedule(qs->netdev); - return 1; -} - -/* - * The MSI-X interrupt handler for an SGE response queue for the non-NAPI case - * (i.e., response queue serviced in hard interrupt). - */ -irqreturn_t t3_sge_intr_msix(int irq, void *cookie) -{ - struct sge_qset *qs = cookie; - struct adapter *adap = qs->netdev->priv; - struct sge_rspq *q = &qs->rspq; - - spin_lock(&q->lock); - if (process_responses(adap, qs, -1) == 0) - q->unhandled_irqs++; - t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) | - V_NEWTIMER(q->next_holdoff) | V_NEWINDEX(q->cidx)); - spin_unlock(&q->lock); - return IRQ_HANDLED; -} - -/* - * The MSI-X interrupt handler for an SGE response queue for the NAPI case - * (i.e., response queue serviced by NAPI polling). - */ -irqreturn_t t3_sge_intr_msix_napi(int irq, void *cookie) -{ - struct sge_qset *qs = cookie; - struct adapter *adap = qs->netdev->priv; - struct sge_rspq *q = &qs->rspq; - - spin_lock(&q->lock); - BUG_ON(napi_is_scheduled(qs->netdev)); - - if (handle_responses(adap, q) < 0) - q->unhandled_irqs++; - spin_unlock(&q->lock); - return IRQ_HANDLED; -} - -/* - * The non-NAPI MSI interrupt handler. This needs to handle data events from - * SGE response queues as well as error and other async events as they all use - * the same MSI vector. We use one SGE response queue per port in this mode - * and protect all response queues with queue 0's lock. - */ -static irqreturn_t t3_intr_msi(int irq, void *cookie) -{ - int new_packets = 0; - struct adapter *adap = cookie; - struct sge_rspq *q = &adap->sge.qs[0].rspq; - - spin_lock(&q->lock); - - if (process_responses(adap, &adap->sge.qs[0], -1)) { - t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) | - V_NEWTIMER(q->next_holdoff) | V_NEWINDEX(q->cidx)); - new_packets = 1; - } - - if (adap->params.nports == 2 && - process_responses(adap, &adap->sge.qs[1], -1)) { - struct sge_rspq *q1 = &adap->sge.qs[1].rspq; - - t3_write_reg(adap, A_SG_GTS, V_RSPQ(q1->cntxt_id) | - V_NEWTIMER(q1->next_holdoff) | - V_NEWINDEX(q1->cidx)); - new_packets = 1; - } - - if (!new_packets && t3_slow_intr_handler(adap) == 0) - q->unhandled_irqs++; - - spin_unlock(&q->lock); - return IRQ_HANDLED; -} - -static int rspq_check_napi(struct net_device *dev, struct sge_rspq *q) -{ - if (!napi_is_scheduled(dev) && is_new_response(&q->desc[q->cidx], q)) { - if (likely(__netif_rx_schedule_prep(dev))) - __netif_rx_schedule(dev); - return 1; - } - return 0; -} - -/* - * The MSI interrupt handler for the NAPI case (i.e., response queues serviced - * by NAPI polling). Handles data events from SGE response queues as well as - * error and other async events as they all use the same MSI vector. We use - * one SGE response queue per port in this mode and protect all response - * queues with queue 0's lock. - */ -irqreturn_t t3_intr_msi_napi(int irq, void *cookie) -{ - int new_packets; - struct adapter *adap = cookie; - struct sge_rspq *q = &adap->sge.qs[0].rspq; - - spin_lock(&q->lock); - - new_packets = rspq_check_napi(adap->sge.qs[0].netdev, q); - if (adap->params.nports == 2) - new_packets += rspq_check_napi(adap->sge.qs[1].netdev, - &adap->sge.qs[1].rspq); - if (!new_packets && t3_slow_intr_handler(adap) == 0) - q->unhandled_irqs++; - - spin_unlock(&q->lock); - return IRQ_HANDLED; -} - -/* - * A helper function that processes responses and issues GTS. - */ -static inline int process_responses_gts(struct adapter *adap, - struct sge_rspq *rq) -{ - int work; - - work = process_responses(adap, rspq_to_qset(rq), -1); - t3_write_reg(adap, A_SG_GTS, V_RSPQ(rq->cntxt_id) | - V_NEWTIMER(rq->next_holdoff) | V_NEWINDEX(rq->cidx)); - return work; -} - -/* - * The legacy INTx interrupt handler. This needs to handle data events from - * SGE response queues as well as error and other async events as they all use - * the same interrupt pin. We use one SGE response queue per port in this mode - * and protect all response queues with queue 0's lock. - */ -static irqreturn_t t3_intr(int irq, void *cookie) -{ - int work_done, w0, w1; - struct adapter *adap = cookie; - struct sge_rspq *q0 = &adap->sge.qs[0].rspq; - struct sge_rspq *q1 = &adap->sge.qs[1].rspq; - - spin_lock(&q0->lock); - - w0 = is_new_response(&q0->desc[q0->cidx], q0); - w1 = adap->params.nports == 2 && - is_new_response(&q1->desc[q1->cidx], q1); - - if (likely(w0 | w1)) { - t3_write_reg(adap, A_PL_CLI, 0); - t3_read_reg(adap, A_PL_CLI); /* flush */ - - if (likely(w0)) - process_responses_gts(adap, q0); - - if (w1) - process_responses_gts(adap, q1); - - work_done = w0 | w1; - } else - work_done = t3_slow_intr_handler(adap); - - spin_unlock(&q0->lock); - return IRQ_RETVAL(work_done != 0); -} - -/* - * Interrupt handler for legacy INTx interrupts for T3B-based cards. - * Handles data events from SGE response queues as well as error and other - * async events as they all use the same interrupt pin. We use one SGE - * response queue per port in this mode and protect all response queues with - * queue 0's lock. - */ -static irqreturn_t t3b_intr(int irq, void *cookie) -{ - u32 map; - struct adapter *adap = cookie; - struct sge_rspq *q0 = &adap->sge.qs[0].rspq; - - t3_write_reg(adap, A_PL_CLI, 0); - map = t3_read_reg(adap, A_SG_DATA_INTR); - - if (unlikely(!map)) /* shared interrupt, most likely */ - return IRQ_NONE; - - spin_lock(&q0->lock); - - if (unlikely(map & F_ERRINTR)) - t3_slow_intr_handler(adap); - - if (likely(map & 1)) - process_responses_gts(adap, q0); - - if (map & 2) - process_responses_gts(adap, &adap->sge.qs[1].rspq); - - spin_unlock(&q0->lock); - return IRQ_HANDLED; -} - -/* - * NAPI interrupt handler for legacy INTx interrupts for T3B-based cards. - * Handles data events from SGE response queues as well as error and other - * async events as they all use the same interrupt pin. We use one SGE - * response queue per port in this mode and protect all response queues with - * queue 0's lock. - */ -static irqreturn_t t3b_intr_napi(int irq, void *cookie) -{ - u32 map; - struct net_device *dev; - struct adapter *adap = cookie; - struct sge_rspq *q0 = &adap->sge.qs[0].rspq; - - t3_write_reg(adap, A_PL_CLI, 0); - map = t3_read_reg(adap, A_SG_DATA_INTR); - - if (unlikely(!map)) /* shared interrupt, most likely */ - return IRQ_NONE; - - spin_lock(&q0->lock); - - if (unlikely(map & F_ERRINTR)) - t3_slow_intr_handler(adap); - - if (likely(map & 1)) { - dev = adap->sge.qs[0].netdev; - - if (likely(__netif_rx_schedule_prep(dev))) - __netif_rx_schedule(dev); - } - if (map & 2) { - dev = adap->sge.qs[1].netdev; - - if (likely(__netif_rx_schedule_prep(dev))) - __netif_rx_schedule(dev); - } - - spin_unlock(&q0->lock); - return IRQ_HANDLED; -} - -/** - * t3_intr_handler - select the top-level interrupt handler - * @adap: the adapter - * @polling: whether using NAPI to service response queues - * - * Selects the top-level interrupt handler based on the type of interrupts - * (MSI-X, MSI, or legacy) and whether NAPI will be used to service the - * response queues. - */ -intr_handler_t t3_intr_handler(struct adapter *adap, int polling) -{ - if (adap->flags & USING_MSIX) - return polling ? t3_sge_intr_msix_napi : t3_sge_intr_msix; - if (adap->flags & USING_MSI) - return polling ? t3_intr_msi_napi : t3_intr_msi; - if (adap->params.rev > 0) - return polling ? t3b_intr_napi : t3b_intr; - return t3_intr; -} - -/** - * t3_sge_err_intr_handler - SGE async event interrupt handler - * @adapter: the adapter - * - * Interrupt handler for SGE asynchronous (non-data) events. - */ -void t3_sge_err_intr_handler(struct adapter *adapter) -{ - unsigned int v, status = t3_read_reg(adapter, A_SG_INT_CAUSE); - - if (status & F_RSPQCREDITOVERFOW) - CH_ALERT(adapter, "SGE response queue credit overflow\n"); - - if (status & F_RSPQDISABLED) { - v = t3_read_reg(adapter, A_SG_RSPQ_FL_STATUS); - - CH_ALERT(adapter, - "packet delivered to disabled response queue " - "(0x%x)\n", (v >> S_RSPQ0DISABLED) & 0xff); - } - - t3_write_reg(adapter, A_SG_INT_CAUSE, status); - if (status & (F_RSPQCREDITOVERFOW | F_RSPQDISABLED)) - t3_fatal_err(adapter); -} - -/** - * sge_timer_cb - perform periodic maintenance of an SGE qset - * @data: the SGE queue set to maintain - * - * Runs periodically from a timer to perform maintenance of an SGE queue - * set. It performs two tasks: - * - * a) Cleans up any completed Tx descriptors that may still be pending. - * Normal descriptor cleanup happens when new packets are added to a Tx - * queue so this timer is relatively infrequent and does any cleanup only - * if the Tx queue has not seen any new packets in a while. We make a - * best effort attempt to reclaim descriptors, in that we don't wait - * around if we cannot get a queue's lock (which most likely is because - * someone else is queueing new packets and so will also handle the clean - * up). Since control queues use immediate data exclusively we don't - * bother cleaning them up here. - * - * b) Replenishes Rx queues that have run out due to memory shortage. - * Normally new Rx buffers are added when existing ones are consumed but - * when out of memory a queue can become empty. We try to add only a few - * buffers here, the queue will be replenished fully as these new buffers - * are used up if memory shortage has subsided. - */ -static void sge_timer_cb(unsigned long data) -{ - spinlock_t *lock; - struct sge_qset *qs = (struct sge_qset *)data; - struct adapter *adap = qs->netdev->priv; - - if (spin_trylock(&qs->txq[TXQ_ETH].lock)) { - reclaim_completed_tx(adap, &qs->txq[TXQ_ETH]); - spin_unlock(&qs->txq[TXQ_ETH].lock); - } - if (spin_trylock(&qs->txq[TXQ_OFLD].lock)) { - reclaim_completed_tx(adap, &qs->txq[TXQ_OFLD]); - spin_unlock(&qs->txq[TXQ_OFLD].lock); - } - lock = (adap->flags & USING_MSIX) ? &qs->rspq.lock : - &adap->sge.qs[0].rspq.lock; - if (spin_trylock_irq(lock)) { - if (!napi_is_scheduled(qs->netdev)) { - if (qs->fl[0].credits < qs->fl[0].size) - __refill_fl(adap, &qs->fl[0]); - if (qs->fl[1].credits < qs->fl[1].size) - __refill_fl(adap, &qs->fl[1]); - } - spin_unlock_irq(lock); - } - mod_timer(&qs->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); -} - -/** - * t3_update_qset_coalesce - update coalescing settings for a queue set - * @qs: the SGE queue set - * @p: new queue set parameters - * - * Update the coalescing settings for an SGE queue set. Nothing is done - * if the queue set is not initialized yet. - */ -void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p) -{ - if (!qs->netdev) - return; - - qs->rspq.holdoff_tmr = max(p->coalesce_usecs * 10, 1U);/* can't be 0 */ - qs->rspq.polling = p->polling; - qs->netdev->poll = p->polling ? napi_rx_handler : ofld_poll; -} - -/** - * t3_sge_alloc_qset - initialize an SGE queue set - * @adapter: the adapter - * @id: the queue set id - * @nports: how many Ethernet ports will be using this queue set - * @irq_vec_idx: the IRQ vector index for response queue interrupts - * @p: configuration parameters for this queue set - * @ntxq: number of Tx queues for the queue set - * @netdev: net device associated with this queue set - * - * Allocate resources and initialize an SGE queue set. A queue set - * comprises a response queue, two Rx free-buffer queues, and up to 3 - * Tx queues. The Tx queues are assigned roles in the order Ethernet - * queue, offload queue, and control queue. - */ -int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, - int irq_vec_idx, const struct qset_params *p, - int ntxq, struct net_device *netdev) -{ - int i, ret = -ENOMEM; - struct sge_qset *q = &adapter->sge.qs[id]; - - init_qset_cntxt(q, id); - init_timer(&q->tx_reclaim_timer); - q->tx_reclaim_timer.data = (unsigned long)q; - q->tx_reclaim_timer.function = sge_timer_cb; - - q->fl[0].desc = alloc_ring(adapter->pdev, p->fl_size, - sizeof(struct rx_desc), - sizeof(struct rx_sw_desc), - &q->fl[0].phys_addr, &q->fl[0].sdesc); - if (!q->fl[0].desc) - goto err; - - q->fl[1].desc = alloc_ring(adapter->pdev, p->jumbo_size, - sizeof(struct rx_desc), - sizeof(struct rx_sw_desc), - &q->fl[1].phys_addr, &q->fl[1].sdesc); - if (!q->fl[1].desc) - goto err; - - q->rspq.desc = alloc_ring(adapter->pdev, p->rspq_size, - sizeof(struct rsp_desc), 0, - &q->rspq.phys_addr, NULL); - if (!q->rspq.desc) - goto err; - - for (i = 0; i < ntxq; ++i) { - /* - * The control queue always uses immediate data so does not - * need to keep track of any sk_buffs. - */ - size_t sz = i == TXQ_CTRL ? 0 : sizeof(struct tx_sw_desc); - - q->txq[i].desc = alloc_ring(adapter->pdev, p->txq_size[i], - sizeof(struct tx_desc), sz, - &q->txq[i].phys_addr, - &q->txq[i].sdesc); - if (!q->txq[i].desc) - goto err; - - q->txq[i].gen = 1; - q->txq[i].size = p->txq_size[i]; - spin_lock_init(&q->txq[i].lock); - skb_queue_head_init(&q->txq[i].sendq); - } - - tasklet_init(&q->txq[TXQ_OFLD].qresume_tsk, restart_offloadq, - (unsigned long)q); - tasklet_init(&q->txq[TXQ_CTRL].qresume_tsk, restart_ctrlq, - (unsigned long)q); - - q->fl[0].gen = q->fl[1].gen = 1; - q->fl[0].size = p->fl_size; - q->fl[1].size = p->jumbo_size; - - q->rspq.gen = 1; - q->rspq.size = p->rspq_size; - spin_lock_init(&q->rspq.lock); - - q->txq[TXQ_ETH].stop_thres = nports * - flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3); - - if (ntxq == 1) { - q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 + - sizeof(struct cpl_rx_pkt); - q->fl[1].buf_size = MAX_FRAME_SIZE + 2 + - sizeof(struct cpl_rx_pkt); - } else { - q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + - sizeof(struct cpl_rx_data); - q->fl[1].buf_size = (16 * 1024) - - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - } - - spin_lock(&adapter->sge.reg_lock); - - /* FL threshold comparison uses < */ - ret = t3_sge_init_rspcntxt(adapter, q->rspq.cntxt_id, irq_vec_idx, - q->rspq.phys_addr, q->rspq.size, - q->fl[0].buf_size, 1, 0); - if (ret) - goto err_unlock; - - for (i = 0; i < SGE_RXQ_PER_SET; ++i) { - ret = t3_sge_init_flcntxt(adapter, q->fl[i].cntxt_id, 0, - q->fl[i].phys_addr, q->fl[i].size, - q->fl[i].buf_size, p->cong_thres, 1, - 0); - if (ret) - goto err_unlock; - } - - ret = t3_sge_init_ecntxt(adapter, q->txq[TXQ_ETH].cntxt_id, USE_GTS, - SGE_CNTXT_ETH, id, q->txq[TXQ_ETH].phys_addr, - q->txq[TXQ_ETH].size, q->txq[TXQ_ETH].token, - 1, 0); - if (ret) - goto err_unlock; - - if (ntxq > 1) { - ret = t3_sge_init_ecntxt(adapter, q->txq[TXQ_OFLD].cntxt_id, - USE_GTS, SGE_CNTXT_OFLD, id, - q->txq[TXQ_OFLD].phys_addr, - q->txq[TXQ_OFLD].size, 0, 1, 0); - if (ret) - goto err_unlock; - } - - if (ntxq > 2) { - ret = t3_sge_init_ecntxt(adapter, q->txq[TXQ_CTRL].cntxt_id, 0, - SGE_CNTXT_CTRL, id, - q->txq[TXQ_CTRL].phys_addr, - q->txq[TXQ_CTRL].size, - q->txq[TXQ_CTRL].token, 1, 0); - if (ret) - goto err_unlock; - } - - spin_unlock(&adapter->sge.reg_lock); - q->netdev = netdev; - t3_update_qset_coalesce(q, p); - - /* - * We use atalk_ptr as a backpointer to a qset. In case a device is - * associated with multiple queue sets only the first one sets - * atalk_ptr. - */ - if (netdev->atalk_ptr == NULL) - netdev->atalk_ptr = q; - - refill_fl(adapter, &q->fl[0], q->fl[0].size, GFP_KERNEL); - refill_fl(adapter, &q->fl[1], q->fl[1].size, GFP_KERNEL); - refill_rspq(adapter, &q->rspq, q->rspq.size - 1); - - t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) | - V_NEWTIMER(q->rspq.holdoff_tmr)); - - mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); - return 0; - - err_unlock: - spin_unlock(&adapter->sge.reg_lock); - err: - t3_free_qset(adapter, q); - return ret; -} - -/** - * t3_free_sge_resources - free SGE resources - * @adap: the adapter - * - * Frees resources used by the SGE queue sets. - */ -void t3_free_sge_resources(struct adapter *adap) -{ - int i; - - for (i = 0; i < SGE_QSETS; ++i) - t3_free_qset(adap, &adap->sge.qs[i]); -} - -/** - * t3_sge_start - enable SGE - * @adap: the adapter - * - * Enables the SGE for DMAs. This is the last step in starting packet - * transfers. - */ -void t3_sge_start(struct adapter *adap) -{ - t3_set_reg_field(adap, A_SG_CONTROL, F_GLOBALENABLE, F_GLOBALENABLE); -} - -/** - * t3_sge_stop - disable SGE operation - * @adap: the adapter - * - * Disables the DMA engine. This can be called in emeregencies (e.g., - * from error interrupts) or from normal process context. In the latter - * case it also disables any pending queue restart tasklets. Note that - * if it is called in interrupt context it cannot disable the restart - * tasklets as it cannot wait, however the tasklets will have no effect - * since the doorbells are disabled and the driver will call this again - * later from process context, at which time the tasklets will be stopped - * if they are still running. - */ -void t3_sge_stop(struct adapter *adap) -{ - t3_set_reg_field(adap, A_SG_CONTROL, F_GLOBALENABLE, 0); - if (!in_interrupt()) { - int i; - - for (i = 0; i < SGE_QSETS; ++i) { - struct sge_qset *qs = &adap->sge.qs[i]; - - tasklet_kill(&qs->txq[TXQ_OFLD].qresume_tsk); - tasklet_kill(&qs->txq[TXQ_CTRL].qresume_tsk); - } - } -} - -/** - * t3_sge_init - initialize SGE - * @adap: the adapter - * @p: the SGE parameters - * - * Performs SGE initialization needed every time after a chip reset. - * We do not initialize any of the queue sets here, instead the driver - * top-level must request those individually. We also do not enable DMA - * here, that should be done after the queues have been set up. - */ -void t3_sge_init(struct adapter *adap, struct sge_params *p) -{ - unsigned int ctrl, ups = ffs(pci_resource_len(adap->pdev, 2) >> 12); - - ctrl = F_DROPPKT | V_PKTSHIFT(2) | F_FLMODE | F_AVOIDCQOVFL | - F_CQCRDTCTRL | - V_HOSTPAGESIZE(PAGE_SHIFT - 11) | F_BIGENDIANINGRESS | - V_USERSPACESIZE(ups ? ups - 1 : 0) | F_ISCSICOALESCING; -#if SGE_NUM_GENBITS == 1 - ctrl |= F_EGRGENCTRL; -#endif - if (adap->params.rev > 0) { - if (!(adap->flags & (USING_MSIX | USING_MSI))) - ctrl |= F_ONEINTMULTQ | F_OPTONEINTMULTQ; - ctrl |= F_CQCRDTCTRL | F_AVOIDCQOVFL; - } - t3_write_reg(adap, A_SG_CONTROL, ctrl); - t3_write_reg(adap, A_SG_EGR_RCQ_DRB_THRSH, V_HIRCQDRBTHRSH(512) | - V_LORCQDRBTHRSH(512)); - t3_write_reg(adap, A_SG_TIMER_TICK, core_ticks_per_usec(adap) / 10); - t3_write_reg(adap, A_SG_CMDQ_CREDIT_TH, V_THRESHOLD(32) | - V_TIMEOUT(200 * core_ticks_per_usec(adap))); - t3_write_reg(adap, A_SG_HI_DRB_HI_THRSH, 1000); - t3_write_reg(adap, A_SG_HI_DRB_LO_THRSH, 256); - t3_write_reg(adap, A_SG_LO_DRB_HI_THRSH, 1000); - t3_write_reg(adap, A_SG_LO_DRB_LO_THRSH, 256); - t3_write_reg(adap, A_SG_OCO_BASE, V_BASE1(0xfff)); - t3_write_reg(adap, A_SG_DRB_PRI_THRESH, 63 * 1024); -} - -/** - * t3_sge_prep - one-time SGE initialization - * @adap: the associated adapter - * @p: SGE parameters - * - * Performs one-time initialization of SGE SW state. Includes determining - * defaults for the assorted SGE parameters, which admins can change until - * they are used to initialize the SGE. - */ -void __devinit t3_sge_prep(struct adapter *adap, struct sge_params *p) -{ - int i; - - p->max_pkt_size = (16 * 1024) - sizeof(struct cpl_rx_data) - - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - - for (i = 0; i < SGE_QSETS; ++i) { - struct qset_params *q = p->qset + i; - - q->polling = adap->params.rev > 0; - q->coalesce_usecs = 5; - q->rspq_size = 1024; - q->fl_size = 4096; - q->jumbo_size = 512; - q->txq_size[TXQ_ETH] = 1024; - q->txq_size[TXQ_OFLD] = 1024; - q->txq_size[TXQ_CTRL] = 256; - q->cong_thres = 0; - } - - spin_lock_init(&adap->sge.reg_lock); -} - -/** - * t3_get_desc - dump an SGE descriptor for debugging purposes - * @qs: the queue set - * @qnum: identifies the specific queue (0..2: Tx, 3:response, 4..5: Rx) - * @idx: the descriptor index in the queue - * @data: where to dump the descriptor contents - * - * Dumps the contents of a HW descriptor of an SGE queue. Returns the - * size of the descriptor. - */ -int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx, - unsigned char *data) -{ - if (qnum >= 6) - return -EINVAL; - - if (qnum < 3) { - if (!qs->txq[qnum].desc || idx >= qs->txq[qnum].size) - return -EINVAL; - memcpy(data, &qs->txq[qnum].desc[idx], sizeof(struct tx_desc)); - return sizeof(struct tx_desc); - } - - if (qnum == 3) { - if (!qs->rspq.desc || idx >= qs->rspq.size) - return -EINVAL; - memcpy(data, &qs->rspq.desc[idx], sizeof(struct rsp_desc)); - return sizeof(struct rsp_desc); - } - - qnum -= 4; - if (!qs->fl[qnum].desc || idx >= qs->fl[qnum].size) - return -EINVAL; - memcpy(data, &qs->fl[qnum].desc[idx], sizeof(struct rx_desc)); - return sizeof(struct rx_desc); -} diff --git a/trunk/drivers/net/cxgb3/sge_defs.h b/trunk/drivers/net/cxgb3/sge_defs.h deleted file mode 100644 index 514869e26a76..000000000000 --- a/trunk/drivers/net/cxgb3/sge_defs.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * This file is automatically generated --- any changes will be lost. - */ - -#ifndef _SGE_DEFS_H -#define _SGE_DEFS_H - -#define S_EC_CREDITS 0 -#define M_EC_CREDITS 0x7FFF -#define V_EC_CREDITS(x) ((x) << S_EC_CREDITS) -#define G_EC_CREDITS(x) (((x) >> S_EC_CREDITS) & M_EC_CREDITS) - -#define S_EC_GTS 15 -#define V_EC_GTS(x) ((x) << S_EC_GTS) -#define F_EC_GTS V_EC_GTS(1U) - -#define S_EC_INDEX 16 -#define M_EC_INDEX 0xFFFF -#define V_EC_INDEX(x) ((x) << S_EC_INDEX) -#define G_EC_INDEX(x) (((x) >> S_EC_INDEX) & M_EC_INDEX) - -#define S_EC_SIZE 0 -#define M_EC_SIZE 0xFFFF -#define V_EC_SIZE(x) ((x) << S_EC_SIZE) -#define G_EC_SIZE(x) (((x) >> S_EC_SIZE) & M_EC_SIZE) - -#define S_EC_BASE_LO 16 -#define M_EC_BASE_LO 0xFFFF -#define V_EC_BASE_LO(x) ((x) << S_EC_BASE_LO) -#define G_EC_BASE_LO(x) (((x) >> S_EC_BASE_LO) & M_EC_BASE_LO) - -#define S_EC_BASE_HI 0 -#define M_EC_BASE_HI 0xF -#define V_EC_BASE_HI(x) ((x) << S_EC_BASE_HI) -#define G_EC_BASE_HI(x) (((x) >> S_EC_BASE_HI) & M_EC_BASE_HI) - -#define S_EC_RESPQ 4 -#define M_EC_RESPQ 0x7 -#define V_EC_RESPQ(x) ((x) << S_EC_RESPQ) -#define G_EC_RESPQ(x) (((x) >> S_EC_RESPQ) & M_EC_RESPQ) - -#define S_EC_TYPE 7 -#define M_EC_TYPE 0x7 -#define V_EC_TYPE(x) ((x) << S_EC_TYPE) -#define G_EC_TYPE(x) (((x) >> S_EC_TYPE) & M_EC_TYPE) - -#define S_EC_GEN 10 -#define V_EC_GEN(x) ((x) << S_EC_GEN) -#define F_EC_GEN V_EC_GEN(1U) - -#define S_EC_UP_TOKEN 11 -#define M_EC_UP_TOKEN 0xFFFFF -#define V_EC_UP_TOKEN(x) ((x) << S_EC_UP_TOKEN) -#define G_EC_UP_TOKEN(x) (((x) >> S_EC_UP_TOKEN) & M_EC_UP_TOKEN) - -#define S_EC_VALID 31 -#define V_EC_VALID(x) ((x) << S_EC_VALID) -#define F_EC_VALID V_EC_VALID(1U) - -#define S_RQ_MSI_VEC 20 -#define M_RQ_MSI_VEC 0x3F -#define V_RQ_MSI_VEC(x) ((x) << S_RQ_MSI_VEC) -#define G_RQ_MSI_VEC(x) (((x) >> S_RQ_MSI_VEC) & M_RQ_MSI_VEC) - -#define S_RQ_INTR_EN 26 -#define V_RQ_INTR_EN(x) ((x) << S_RQ_INTR_EN) -#define F_RQ_INTR_EN V_RQ_INTR_EN(1U) - -#define S_RQ_GEN 28 -#define V_RQ_GEN(x) ((x) << S_RQ_GEN) -#define F_RQ_GEN V_RQ_GEN(1U) - -#define S_CQ_INDEX 0 -#define M_CQ_INDEX 0xFFFF -#define V_CQ_INDEX(x) ((x) << S_CQ_INDEX) -#define G_CQ_INDEX(x) (((x) >> S_CQ_INDEX) & M_CQ_INDEX) - -#define S_CQ_SIZE 16 -#define M_CQ_SIZE 0xFFFF -#define V_CQ_SIZE(x) ((x) << S_CQ_SIZE) -#define G_CQ_SIZE(x) (((x) >> S_CQ_SIZE) & M_CQ_SIZE) - -#define S_CQ_BASE_HI 0 -#define M_CQ_BASE_HI 0xFFFFF -#define V_CQ_BASE_HI(x) ((x) << S_CQ_BASE_HI) -#define G_CQ_BASE_HI(x) (((x) >> S_CQ_BASE_HI) & M_CQ_BASE_HI) - -#define S_CQ_RSPQ 20 -#define M_CQ_RSPQ 0x3F -#define V_CQ_RSPQ(x) ((x) << S_CQ_RSPQ) -#define G_CQ_RSPQ(x) (((x) >> S_CQ_RSPQ) & M_CQ_RSPQ) - -#define S_CQ_ASYNC_NOTIF 26 -#define V_CQ_ASYNC_NOTIF(x) ((x) << S_CQ_ASYNC_NOTIF) -#define F_CQ_ASYNC_NOTIF V_CQ_ASYNC_NOTIF(1U) - -#define S_CQ_ARMED 27 -#define V_CQ_ARMED(x) ((x) << S_CQ_ARMED) -#define F_CQ_ARMED V_CQ_ARMED(1U) - -#define S_CQ_ASYNC_NOTIF_SOL 28 -#define V_CQ_ASYNC_NOTIF_SOL(x) ((x) << S_CQ_ASYNC_NOTIF_SOL) -#define F_CQ_ASYNC_NOTIF_SOL V_CQ_ASYNC_NOTIF_SOL(1U) - -#define S_CQ_GEN 29 -#define V_CQ_GEN(x) ((x) << S_CQ_GEN) -#define F_CQ_GEN V_CQ_GEN(1U) - -#define S_CQ_OVERFLOW_MODE 31 -#define V_CQ_OVERFLOW_MODE(x) ((x) << S_CQ_OVERFLOW_MODE) -#define F_CQ_OVERFLOW_MODE V_CQ_OVERFLOW_MODE(1U) - -#define S_CQ_CREDITS 0 -#define M_CQ_CREDITS 0xFFFF -#define V_CQ_CREDITS(x) ((x) << S_CQ_CREDITS) -#define G_CQ_CREDITS(x) (((x) >> S_CQ_CREDITS) & M_CQ_CREDITS) - -#define S_CQ_CREDIT_THRES 16 -#define M_CQ_CREDIT_THRES 0x1FFF -#define V_CQ_CREDIT_THRES(x) ((x) << S_CQ_CREDIT_THRES) -#define G_CQ_CREDIT_THRES(x) (((x) >> S_CQ_CREDIT_THRES) & M_CQ_CREDIT_THRES) - -#define S_FL_BASE_HI 0 -#define M_FL_BASE_HI 0xFFFFF -#define V_FL_BASE_HI(x) ((x) << S_FL_BASE_HI) -#define G_FL_BASE_HI(x) (((x) >> S_FL_BASE_HI) & M_FL_BASE_HI) - -#define S_FL_INDEX_LO 20 -#define M_FL_INDEX_LO 0xFFF -#define V_FL_INDEX_LO(x) ((x) << S_FL_INDEX_LO) -#define G_FL_INDEX_LO(x) (((x) >> S_FL_INDEX_LO) & M_FL_INDEX_LO) - -#define S_FL_INDEX_HI 0 -#define M_FL_INDEX_HI 0xF -#define V_FL_INDEX_HI(x) ((x) << S_FL_INDEX_HI) -#define G_FL_INDEX_HI(x) (((x) >> S_FL_INDEX_HI) & M_FL_INDEX_HI) - -#define S_FL_SIZE 4 -#define M_FL_SIZE 0xFFFF -#define V_FL_SIZE(x) ((x) << S_FL_SIZE) -#define G_FL_SIZE(x) (((x) >> S_FL_SIZE) & M_FL_SIZE) - -#define S_FL_GEN 20 -#define V_FL_GEN(x) ((x) << S_FL_GEN) -#define F_FL_GEN V_FL_GEN(1U) - -#define S_FL_ENTRY_SIZE_LO 21 -#define M_FL_ENTRY_SIZE_LO 0x7FF -#define V_FL_ENTRY_SIZE_LO(x) ((x) << S_FL_ENTRY_SIZE_LO) -#define G_FL_ENTRY_SIZE_LO(x) (((x) >> S_FL_ENTRY_SIZE_LO) & M_FL_ENTRY_SIZE_LO) - -#define S_FL_ENTRY_SIZE_HI 0 -#define M_FL_ENTRY_SIZE_HI 0x1FFFFF -#define V_FL_ENTRY_SIZE_HI(x) ((x) << S_FL_ENTRY_SIZE_HI) -#define G_FL_ENTRY_SIZE_HI(x) (((x) >> S_FL_ENTRY_SIZE_HI) & M_FL_ENTRY_SIZE_HI) - -#define S_FL_CONG_THRES 21 -#define M_FL_CONG_THRES 0x3FF -#define V_FL_CONG_THRES(x) ((x) << S_FL_CONG_THRES) -#define G_FL_CONG_THRES(x) (((x) >> S_FL_CONG_THRES) & M_FL_CONG_THRES) - -#define S_FL_GTS 31 -#define V_FL_GTS(x) ((x) << S_FL_GTS) -#define F_FL_GTS V_FL_GTS(1U) - -#define S_FLD_GEN1 31 -#define V_FLD_GEN1(x) ((x) << S_FLD_GEN1) -#define F_FLD_GEN1 V_FLD_GEN1(1U) - -#define S_FLD_GEN2 0 -#define V_FLD_GEN2(x) ((x) << S_FLD_GEN2) -#define F_FLD_GEN2 V_FLD_GEN2(1U) - -#define S_RSPD_TXQ1_CR 0 -#define M_RSPD_TXQ1_CR 0x7F -#define V_RSPD_TXQ1_CR(x) ((x) << S_RSPD_TXQ1_CR) -#define G_RSPD_TXQ1_CR(x) (((x) >> S_RSPD_TXQ1_CR) & M_RSPD_TXQ1_CR) - -#define S_RSPD_TXQ1_GTS 7 -#define V_RSPD_TXQ1_GTS(x) ((x) << S_RSPD_TXQ1_GTS) -#define F_RSPD_TXQ1_GTS V_RSPD_TXQ1_GTS(1U) - -#define S_RSPD_TXQ2_CR 8 -#define M_RSPD_TXQ2_CR 0x7F -#define V_RSPD_TXQ2_CR(x) ((x) << S_RSPD_TXQ2_CR) -#define G_RSPD_TXQ2_CR(x) (((x) >> S_RSPD_TXQ2_CR) & M_RSPD_TXQ2_CR) - -#define S_RSPD_TXQ2_GTS 15 -#define V_RSPD_TXQ2_GTS(x) ((x) << S_RSPD_TXQ2_GTS) -#define F_RSPD_TXQ2_GTS V_RSPD_TXQ2_GTS(1U) - -#define S_RSPD_TXQ0_CR 16 -#define M_RSPD_TXQ0_CR 0x7F -#define V_RSPD_TXQ0_CR(x) ((x) << S_RSPD_TXQ0_CR) -#define G_RSPD_TXQ0_CR(x) (((x) >> S_RSPD_TXQ0_CR) & M_RSPD_TXQ0_CR) - -#define S_RSPD_TXQ0_GTS 23 -#define V_RSPD_TXQ0_GTS(x) ((x) << S_RSPD_TXQ0_GTS) -#define F_RSPD_TXQ0_GTS V_RSPD_TXQ0_GTS(1U) - -#define S_RSPD_EOP 24 -#define V_RSPD_EOP(x) ((x) << S_RSPD_EOP) -#define F_RSPD_EOP V_RSPD_EOP(1U) - -#define S_RSPD_SOP 25 -#define V_RSPD_SOP(x) ((x) << S_RSPD_SOP) -#define F_RSPD_SOP V_RSPD_SOP(1U) - -#define S_RSPD_ASYNC_NOTIF 26 -#define V_RSPD_ASYNC_NOTIF(x) ((x) << S_RSPD_ASYNC_NOTIF) -#define F_RSPD_ASYNC_NOTIF V_RSPD_ASYNC_NOTIF(1U) - -#define S_RSPD_FL0_GTS 27 -#define V_RSPD_FL0_GTS(x) ((x) << S_RSPD_FL0_GTS) -#define F_RSPD_FL0_GTS V_RSPD_FL0_GTS(1U) - -#define S_RSPD_FL1_GTS 28 -#define V_RSPD_FL1_GTS(x) ((x) << S_RSPD_FL1_GTS) -#define F_RSPD_FL1_GTS V_RSPD_FL1_GTS(1U) - -#define S_RSPD_IMM_DATA_VALID 29 -#define V_RSPD_IMM_DATA_VALID(x) ((x) << S_RSPD_IMM_DATA_VALID) -#define F_RSPD_IMM_DATA_VALID V_RSPD_IMM_DATA_VALID(1U) - -#define S_RSPD_OFFLOAD 30 -#define V_RSPD_OFFLOAD(x) ((x) << S_RSPD_OFFLOAD) -#define F_RSPD_OFFLOAD V_RSPD_OFFLOAD(1U) - -#define S_RSPD_GEN1 31 -#define V_RSPD_GEN1(x) ((x) << S_RSPD_GEN1) -#define F_RSPD_GEN1 V_RSPD_GEN1(1U) - -#define S_RSPD_LEN 0 -#define M_RSPD_LEN 0x7FFFFFFF -#define V_RSPD_LEN(x) ((x) << S_RSPD_LEN) -#define G_RSPD_LEN(x) (((x) >> S_RSPD_LEN) & M_RSPD_LEN) - -#define S_RSPD_FLQ 31 -#define V_RSPD_FLQ(x) ((x) << S_RSPD_FLQ) -#define F_RSPD_FLQ V_RSPD_FLQ(1U) - -#define S_RSPD_GEN2 0 -#define V_RSPD_GEN2(x) ((x) << S_RSPD_GEN2) -#define F_RSPD_GEN2 V_RSPD_GEN2(1U) - -#define S_RSPD_INR_VEC 1 -#define M_RSPD_INR_VEC 0x7F -#define V_RSPD_INR_VEC(x) ((x) << S_RSPD_INR_VEC) -#define G_RSPD_INR_VEC(x) (((x) >> S_RSPD_INR_VEC) & M_RSPD_INR_VEC) - -#endif /* _SGE_DEFS_H */ diff --git a/trunk/drivers/net/cxgb3/t3_cpl.h b/trunk/drivers/net/cxgb3/t3_cpl.h deleted file mode 100644 index b7a1a310dfd4..000000000000 --- a/trunk/drivers/net/cxgb3/t3_cpl.h +++ /dev/null @@ -1,1444 +0,0 @@ -/* - * Copyright (c) 2004-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef T3_CPL_H -#define T3_CPL_H - -#if !defined(__LITTLE_ENDIAN_BITFIELD) && !defined(__BIG_ENDIAN_BITFIELD) -# include -#endif - -enum CPL_opcode { - CPL_PASS_OPEN_REQ = 0x1, - CPL_PASS_ACCEPT_RPL = 0x2, - CPL_ACT_OPEN_REQ = 0x3, - CPL_SET_TCB = 0x4, - CPL_SET_TCB_FIELD = 0x5, - CPL_GET_TCB = 0x6, - CPL_PCMD = 0x7, - CPL_CLOSE_CON_REQ = 0x8, - CPL_CLOSE_LISTSRV_REQ = 0x9, - CPL_ABORT_REQ = 0xA, - CPL_ABORT_RPL = 0xB, - CPL_TX_DATA = 0xC, - CPL_RX_DATA_ACK = 0xD, - CPL_TX_PKT = 0xE, - CPL_RTE_DELETE_REQ = 0xF, - CPL_RTE_WRITE_REQ = 0x10, - CPL_RTE_READ_REQ = 0x11, - CPL_L2T_WRITE_REQ = 0x12, - CPL_L2T_READ_REQ = 0x13, - CPL_SMT_WRITE_REQ = 0x14, - CPL_SMT_READ_REQ = 0x15, - CPL_TX_PKT_LSO = 0x16, - CPL_PCMD_READ = 0x17, - CPL_BARRIER = 0x18, - CPL_TID_RELEASE = 0x1A, - - CPL_CLOSE_LISTSRV_RPL = 0x20, - CPL_ERROR = 0x21, - CPL_GET_TCB_RPL = 0x22, - CPL_L2T_WRITE_RPL = 0x23, - CPL_PCMD_READ_RPL = 0x24, - CPL_PCMD_RPL = 0x25, - CPL_PEER_CLOSE = 0x26, - CPL_RTE_DELETE_RPL = 0x27, - CPL_RTE_WRITE_RPL = 0x28, - CPL_RX_DDP_COMPLETE = 0x29, - CPL_RX_PHYS_ADDR = 0x2A, - CPL_RX_PKT = 0x2B, - CPL_RX_URG_NOTIFY = 0x2C, - CPL_SET_TCB_RPL = 0x2D, - CPL_SMT_WRITE_RPL = 0x2E, - CPL_TX_DATA_ACK = 0x2F, - - CPL_ABORT_REQ_RSS = 0x30, - CPL_ABORT_RPL_RSS = 0x31, - CPL_CLOSE_CON_RPL = 0x32, - CPL_ISCSI_HDR = 0x33, - CPL_L2T_READ_RPL = 0x34, - CPL_RDMA_CQE = 0x35, - CPL_RDMA_CQE_READ_RSP = 0x36, - CPL_RDMA_CQE_ERR = 0x37, - CPL_RTE_READ_RPL = 0x38, - CPL_RX_DATA = 0x39, - - CPL_ACT_OPEN_RPL = 0x40, - CPL_PASS_OPEN_RPL = 0x41, - CPL_RX_DATA_DDP = 0x42, - CPL_SMT_READ_RPL = 0x43, - - CPL_ACT_ESTABLISH = 0x50, - CPL_PASS_ESTABLISH = 0x51, - - CPL_PASS_ACCEPT_REQ = 0x70, - - CPL_ASYNC_NOTIF = 0x80, /* fake opcode for async notifications */ - - CPL_TX_DMA_ACK = 0xA0, - CPL_RDMA_READ_REQ = 0xA1, - CPL_RDMA_TERMINATE = 0xA2, - CPL_TRACE_PKT = 0xA3, - CPL_RDMA_EC_STATUS = 0xA5, - - NUM_CPL_CMDS /* must be last and previous entries must be sorted */ -}; - -enum CPL_error { - CPL_ERR_NONE = 0, - CPL_ERR_TCAM_PARITY = 1, - CPL_ERR_TCAM_FULL = 3, - CPL_ERR_CONN_RESET = 20, - CPL_ERR_CONN_EXIST = 22, - CPL_ERR_ARP_MISS = 23, - CPL_ERR_BAD_SYN = 24, - CPL_ERR_CONN_TIMEDOUT = 30, - CPL_ERR_XMIT_TIMEDOUT = 31, - CPL_ERR_PERSIST_TIMEDOUT = 32, - CPL_ERR_FINWAIT2_TIMEDOUT = 33, - CPL_ERR_KEEPALIVE_TIMEDOUT = 34, - CPL_ERR_RTX_NEG_ADVICE = 35, - CPL_ERR_PERSIST_NEG_ADVICE = 36, - CPL_ERR_ABORT_FAILED = 42, - CPL_ERR_GENERAL = 99 -}; - -enum { - CPL_CONN_POLICY_AUTO = 0, - CPL_CONN_POLICY_ASK = 1, - CPL_CONN_POLICY_DENY = 3 -}; - -enum { - ULP_MODE_NONE = 0, - ULP_MODE_ISCSI = 2, - ULP_MODE_RDMA = 4, - ULP_MODE_TCPDDP = 5 -}; - -enum { - ULP_CRC_HEADER = 1 << 0, - ULP_CRC_DATA = 1 << 1 -}; - -enum { - CPL_PASS_OPEN_ACCEPT, - CPL_PASS_OPEN_REJECT -}; - -enum { - CPL_ABORT_SEND_RST = 0, - CPL_ABORT_NO_RST, - CPL_ABORT_POST_CLOSE_REQ = 2 -}; - -enum { /* TX_PKT_LSO ethernet types */ - CPL_ETH_II, - CPL_ETH_II_VLAN, - CPL_ETH_802_3, - CPL_ETH_802_3_VLAN -}; - -enum { /* TCP congestion control algorithms */ - CONG_ALG_RENO, - CONG_ALG_TAHOE, - CONG_ALG_NEWRENO, - CONG_ALG_HIGHSPEED -}; - -union opcode_tid { - __be32 opcode_tid; - __u8 opcode; -}; - -#define S_OPCODE 24 -#define V_OPCODE(x) ((x) << S_OPCODE) -#define G_OPCODE(x) (((x) >> S_OPCODE) & 0xFF) -#define G_TID(x) ((x) & 0xFFFFFF) - -/* tid is assumed to be 24-bits */ -#define MK_OPCODE_TID(opcode, tid) (V_OPCODE(opcode) | (tid)) - -#define OPCODE_TID(cmd) ((cmd)->ot.opcode_tid) - -/* extract the TID from a CPL command */ -#define GET_TID(cmd) (G_TID(ntohl(OPCODE_TID(cmd)))) - -struct tcp_options { - __be16 mss; - __u8 wsf; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8:5; - __u8 ecn:1; - __u8 sack:1; - __u8 tstamp:1; -#else - __u8 tstamp:1; - __u8 sack:1; - __u8 ecn:1; - __u8:5; -#endif -}; - -struct rss_header { - __u8 opcode; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 cpu_idx:6; - __u8 hash_type:2; -#else - __u8 hash_type:2; - __u8 cpu_idx:6; -#endif - __be16 cq_idx; - __be32 rss_hash_val; -}; - -#ifndef CHELSIO_FW -struct work_request_hdr { - __be32 wr_hi; - __be32 wr_lo; -}; - -/* wr_hi fields */ -#define S_WR_SGE_CREDITS 0 -#define M_WR_SGE_CREDITS 0xFF -#define V_WR_SGE_CREDITS(x) ((x) << S_WR_SGE_CREDITS) -#define G_WR_SGE_CREDITS(x) (((x) >> S_WR_SGE_CREDITS) & M_WR_SGE_CREDITS) - -#define S_WR_SGLSFLT 8 -#define M_WR_SGLSFLT 0xFF -#define V_WR_SGLSFLT(x) ((x) << S_WR_SGLSFLT) -#define G_WR_SGLSFLT(x) (((x) >> S_WR_SGLSFLT) & M_WR_SGLSFLT) - -#define S_WR_BCNTLFLT 16 -#define M_WR_BCNTLFLT 0xF -#define V_WR_BCNTLFLT(x) ((x) << S_WR_BCNTLFLT) -#define G_WR_BCNTLFLT(x) (((x) >> S_WR_BCNTLFLT) & M_WR_BCNTLFLT) - -#define S_WR_DATATYPE 20 -#define V_WR_DATATYPE(x) ((x) << S_WR_DATATYPE) -#define F_WR_DATATYPE V_WR_DATATYPE(1U) - -#define S_WR_COMPL 21 -#define V_WR_COMPL(x) ((x) << S_WR_COMPL) -#define F_WR_COMPL V_WR_COMPL(1U) - -#define S_WR_EOP 22 -#define V_WR_EOP(x) ((x) << S_WR_EOP) -#define F_WR_EOP V_WR_EOP(1U) - -#define S_WR_SOP 23 -#define V_WR_SOP(x) ((x) << S_WR_SOP) -#define F_WR_SOP V_WR_SOP(1U) - -#define S_WR_OP 24 -#define M_WR_OP 0xFF -#define V_WR_OP(x) ((x) << S_WR_OP) -#define G_WR_OP(x) (((x) >> S_WR_OP) & M_WR_OP) - -/* wr_lo fields */ -#define S_WR_LEN 0 -#define M_WR_LEN 0xFF -#define V_WR_LEN(x) ((x) << S_WR_LEN) -#define G_WR_LEN(x) (((x) >> S_WR_LEN) & M_WR_LEN) - -#define S_WR_TID 8 -#define M_WR_TID 0xFFFFF -#define V_WR_TID(x) ((x) << S_WR_TID) -#define G_WR_TID(x) (((x) >> S_WR_TID) & M_WR_TID) - -#define S_WR_CR_FLUSH 30 -#define V_WR_CR_FLUSH(x) ((x) << S_WR_CR_FLUSH) -#define F_WR_CR_FLUSH V_WR_CR_FLUSH(1U) - -#define S_WR_GEN 31 -#define V_WR_GEN(x) ((x) << S_WR_GEN) -#define F_WR_GEN V_WR_GEN(1U) - -# define WR_HDR struct work_request_hdr wr -# define RSS_HDR -#else -# define WR_HDR -# define RSS_HDR struct rss_header rss_hdr; -#endif - -/* option 0 lower-half fields */ -#define S_CPL_STATUS 0 -#define M_CPL_STATUS 0xFF -#define V_CPL_STATUS(x) ((x) << S_CPL_STATUS) -#define G_CPL_STATUS(x) (((x) >> S_CPL_STATUS) & M_CPL_STATUS) - -#define S_INJECT_TIMER 6 -#define V_INJECT_TIMER(x) ((x) << S_INJECT_TIMER) -#define F_INJECT_TIMER V_INJECT_TIMER(1U) - -#define S_NO_OFFLOAD 7 -#define V_NO_OFFLOAD(x) ((x) << S_NO_OFFLOAD) -#define F_NO_OFFLOAD V_NO_OFFLOAD(1U) - -#define S_ULP_MODE 8 -#define M_ULP_MODE 0xF -#define V_ULP_MODE(x) ((x) << S_ULP_MODE) -#define G_ULP_MODE(x) (((x) >> S_ULP_MODE) & M_ULP_MODE) - -#define S_RCV_BUFSIZ 12 -#define M_RCV_BUFSIZ 0x3FFF -#define V_RCV_BUFSIZ(x) ((x) << S_RCV_BUFSIZ) -#define G_RCV_BUFSIZ(x) (((x) >> S_RCV_BUFSIZ) & M_RCV_BUFSIZ) - -#define S_TOS 26 -#define M_TOS 0x3F -#define V_TOS(x) ((x) << S_TOS) -#define G_TOS(x) (((x) >> S_TOS) & M_TOS) - -/* option 0 upper-half fields */ -#define S_DELACK 0 -#define V_DELACK(x) ((x) << S_DELACK) -#define F_DELACK V_DELACK(1U) - -#define S_NO_CONG 1 -#define V_NO_CONG(x) ((x) << S_NO_CONG) -#define F_NO_CONG V_NO_CONG(1U) - -#define S_SRC_MAC_SEL 2 -#define M_SRC_MAC_SEL 0x3 -#define V_SRC_MAC_SEL(x) ((x) << S_SRC_MAC_SEL) -#define G_SRC_MAC_SEL(x) (((x) >> S_SRC_MAC_SEL) & M_SRC_MAC_SEL) - -#define S_L2T_IDX 4 -#define M_L2T_IDX 0x7FF -#define V_L2T_IDX(x) ((x) << S_L2T_IDX) -#define G_L2T_IDX(x) (((x) >> S_L2T_IDX) & M_L2T_IDX) - -#define S_TX_CHANNEL 15 -#define V_TX_CHANNEL(x) ((x) << S_TX_CHANNEL) -#define F_TX_CHANNEL V_TX_CHANNEL(1U) - -#define S_TCAM_BYPASS 16 -#define V_TCAM_BYPASS(x) ((x) << S_TCAM_BYPASS) -#define F_TCAM_BYPASS V_TCAM_BYPASS(1U) - -#define S_NAGLE 17 -#define V_NAGLE(x) ((x) << S_NAGLE) -#define F_NAGLE V_NAGLE(1U) - -#define S_WND_SCALE 18 -#define M_WND_SCALE 0xF -#define V_WND_SCALE(x) ((x) << S_WND_SCALE) -#define G_WND_SCALE(x) (((x) >> S_WND_SCALE) & M_WND_SCALE) - -#define S_KEEP_ALIVE 22 -#define V_KEEP_ALIVE(x) ((x) << S_KEEP_ALIVE) -#define F_KEEP_ALIVE V_KEEP_ALIVE(1U) - -#define S_MAX_RETRANS 23 -#define M_MAX_RETRANS 0xF -#define V_MAX_RETRANS(x) ((x) << S_MAX_RETRANS) -#define G_MAX_RETRANS(x) (((x) >> S_MAX_RETRANS) & M_MAX_RETRANS) - -#define S_MAX_RETRANS_OVERRIDE 27 -#define V_MAX_RETRANS_OVERRIDE(x) ((x) << S_MAX_RETRANS_OVERRIDE) -#define F_MAX_RETRANS_OVERRIDE V_MAX_RETRANS_OVERRIDE(1U) - -#define S_MSS_IDX 28 -#define M_MSS_IDX 0xF -#define V_MSS_IDX(x) ((x) << S_MSS_IDX) -#define G_MSS_IDX(x) (((x) >> S_MSS_IDX) & M_MSS_IDX) - -/* option 1 fields */ -#define S_RSS_ENABLE 0 -#define V_RSS_ENABLE(x) ((x) << S_RSS_ENABLE) -#define F_RSS_ENABLE V_RSS_ENABLE(1U) - -#define S_RSS_MASK_LEN 1 -#define M_RSS_MASK_LEN 0x7 -#define V_RSS_MASK_LEN(x) ((x) << S_RSS_MASK_LEN) -#define G_RSS_MASK_LEN(x) (((x) >> S_RSS_MASK_LEN) & M_RSS_MASK_LEN) - -#define S_CPU_IDX 4 -#define M_CPU_IDX 0x3F -#define V_CPU_IDX(x) ((x) << S_CPU_IDX) -#define G_CPU_IDX(x) (((x) >> S_CPU_IDX) & M_CPU_IDX) - -#define S_MAC_MATCH_VALID 18 -#define V_MAC_MATCH_VALID(x) ((x) << S_MAC_MATCH_VALID) -#define F_MAC_MATCH_VALID V_MAC_MATCH_VALID(1U) - -#define S_CONN_POLICY 19 -#define M_CONN_POLICY 0x3 -#define V_CONN_POLICY(x) ((x) << S_CONN_POLICY) -#define G_CONN_POLICY(x) (((x) >> S_CONN_POLICY) & M_CONN_POLICY) - -#define S_SYN_DEFENSE 21 -#define V_SYN_DEFENSE(x) ((x) << S_SYN_DEFENSE) -#define F_SYN_DEFENSE V_SYN_DEFENSE(1U) - -#define S_VLAN_PRI 22 -#define M_VLAN_PRI 0x3 -#define V_VLAN_PRI(x) ((x) << S_VLAN_PRI) -#define G_VLAN_PRI(x) (((x) >> S_VLAN_PRI) & M_VLAN_PRI) - -#define S_VLAN_PRI_VALID 24 -#define V_VLAN_PRI_VALID(x) ((x) << S_VLAN_PRI_VALID) -#define F_VLAN_PRI_VALID V_VLAN_PRI_VALID(1U) - -#define S_PKT_TYPE 25 -#define M_PKT_TYPE 0x3 -#define V_PKT_TYPE(x) ((x) << S_PKT_TYPE) -#define G_PKT_TYPE(x) (((x) >> S_PKT_TYPE) & M_PKT_TYPE) - -#define S_MAC_MATCH 27 -#define M_MAC_MATCH 0x1F -#define V_MAC_MATCH(x) ((x) << S_MAC_MATCH) -#define G_MAC_MATCH(x) (((x) >> S_MAC_MATCH) & M_MAC_MATCH) - -/* option 2 fields */ -#define S_CPU_INDEX 0 -#define M_CPU_INDEX 0x7F -#define V_CPU_INDEX(x) ((x) << S_CPU_INDEX) -#define G_CPU_INDEX(x) (((x) >> S_CPU_INDEX) & M_CPU_INDEX) - -#define S_CPU_INDEX_VALID 7 -#define V_CPU_INDEX_VALID(x) ((x) << S_CPU_INDEX_VALID) -#define F_CPU_INDEX_VALID V_CPU_INDEX_VALID(1U) - -#define S_RX_COALESCE 8 -#define M_RX_COALESCE 0x3 -#define V_RX_COALESCE(x) ((x) << S_RX_COALESCE) -#define G_RX_COALESCE(x) (((x) >> S_RX_COALESCE) & M_RX_COALESCE) - -#define S_RX_COALESCE_VALID 10 -#define V_RX_COALESCE_VALID(x) ((x) << S_RX_COALESCE_VALID) -#define F_RX_COALESCE_VALID V_RX_COALESCE_VALID(1U) - -#define S_CONG_CONTROL_FLAVOR 11 -#define M_CONG_CONTROL_FLAVOR 0x3 -#define V_CONG_CONTROL_FLAVOR(x) ((x) << S_CONG_CONTROL_FLAVOR) -#define G_CONG_CONTROL_FLAVOR(x) (((x) >> S_CONG_CONTROL_FLAVOR) & M_CONG_CONTROL_FLAVOR) - -#define S_PACING_FLAVOR 13 -#define M_PACING_FLAVOR 0x3 -#define V_PACING_FLAVOR(x) ((x) << S_PACING_FLAVOR) -#define G_PACING_FLAVOR(x) (((x) >> S_PACING_FLAVOR) & M_PACING_FLAVOR) - -#define S_FLAVORS_VALID 15 -#define V_FLAVORS_VALID(x) ((x) << S_FLAVORS_VALID) -#define F_FLAVORS_VALID V_FLAVORS_VALID(1U) - -#define S_RX_FC_DISABLE 16 -#define V_RX_FC_DISABLE(x) ((x) << S_RX_FC_DISABLE) -#define F_RX_FC_DISABLE V_RX_FC_DISABLE(1U) - -#define S_RX_FC_VALID 17 -#define V_RX_FC_VALID(x) ((x) << S_RX_FC_VALID) -#define F_RX_FC_VALID V_RX_FC_VALID(1U) - -struct cpl_pass_open_req { - WR_HDR; - union opcode_tid ot; - __be16 local_port; - __be16 peer_port; - __be32 local_ip; - __be32 peer_ip; - __be32 opt0h; - __be32 opt0l; - __be32 peer_netmask; - __be32 opt1; -}; - -struct cpl_pass_open_rpl { - RSS_HDR union opcode_tid ot; - __be16 local_port; - __be16 peer_port; - __be32 local_ip; - __be32 peer_ip; - __u8 resvd[7]; - __u8 status; -}; - -struct cpl_pass_establish { - RSS_HDR union opcode_tid ot; - __be16 local_port; - __be16 peer_port; - __be32 local_ip; - __be32 peer_ip; - __be32 tos_tid; - __be16 l2t_idx; - __be16 tcp_opt; - __be32 snd_isn; - __be32 rcv_isn; -}; - -/* cpl_pass_establish.tos_tid fields */ -#define S_PASS_OPEN_TID 0 -#define M_PASS_OPEN_TID 0xFFFFFF -#define V_PASS_OPEN_TID(x) ((x) << S_PASS_OPEN_TID) -#define G_PASS_OPEN_TID(x) (((x) >> S_PASS_OPEN_TID) & M_PASS_OPEN_TID) - -#define S_PASS_OPEN_TOS 24 -#define M_PASS_OPEN_TOS 0xFF -#define V_PASS_OPEN_TOS(x) ((x) << S_PASS_OPEN_TOS) -#define G_PASS_OPEN_TOS(x) (((x) >> S_PASS_OPEN_TOS) & M_PASS_OPEN_TOS) - -/* cpl_pass_establish.l2t_idx fields */ -#define S_L2T_IDX16 5 -#define M_L2T_IDX16 0x7FF -#define V_L2T_IDX16(x) ((x) << S_L2T_IDX16) -#define G_L2T_IDX16(x) (((x) >> S_L2T_IDX16) & M_L2T_IDX16) - -/* cpl_pass_establish.tcp_opt fields (also applies act_open_establish) */ -#define G_TCPOPT_WSCALE_OK(x) (((x) >> 5) & 1) -#define G_TCPOPT_SACK(x) (((x) >> 6) & 1) -#define G_TCPOPT_TSTAMP(x) (((x) >> 7) & 1) -#define G_TCPOPT_SND_WSCALE(x) (((x) >> 8) & 0xf) -#define G_TCPOPT_MSS(x) (((x) >> 12) & 0xf) - -struct cpl_pass_accept_req { - RSS_HDR union opcode_tid ot; - __be16 local_port; - __be16 peer_port; - __be32 local_ip; - __be32 peer_ip; - __be32 tos_tid; - struct tcp_options tcp_options; - __u8 dst_mac[6]; - __be16 vlan_tag; - __u8 src_mac[6]; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8:3; - __u8 addr_idx:3; - __u8 port_idx:1; - __u8 exact_match:1; -#else - __u8 exact_match:1; - __u8 port_idx:1; - __u8 addr_idx:3; - __u8:3; -#endif - __u8 rsvd; - __be32 rcv_isn; - __be32 rsvd2; -}; - -struct cpl_pass_accept_rpl { - WR_HDR; - union opcode_tid ot; - __be32 opt2; - __be32 rsvd; - __be32 peer_ip; - __be32 opt0h; - __be32 opt0l_status; -}; - -struct cpl_act_open_req { - WR_HDR; - union opcode_tid ot; - __be16 local_port; - __be16 peer_port; - __be32 local_ip; - __be32 peer_ip; - __be32 opt0h; - __be32 opt0l; - __be32 params; - __be32 opt2; -}; - -/* cpl_act_open_req.params fields */ -#define S_AOPEN_VLAN_PRI 9 -#define M_AOPEN_VLAN_PRI 0x3 -#define V_AOPEN_VLAN_PRI(x) ((x) << S_AOPEN_VLAN_PRI) -#define G_AOPEN_VLAN_PRI(x) (((x) >> S_AOPEN_VLAN_PRI) & M_AOPEN_VLAN_PRI) - -#define S_AOPEN_VLAN_PRI_VALID 11 -#define V_AOPEN_VLAN_PRI_VALID(x) ((x) << S_AOPEN_VLAN_PRI_VALID) -#define F_AOPEN_VLAN_PRI_VALID V_AOPEN_VLAN_PRI_VALID(1U) - -#define S_AOPEN_PKT_TYPE 12 -#define M_AOPEN_PKT_TYPE 0x3 -#define V_AOPEN_PKT_TYPE(x) ((x) << S_AOPEN_PKT_TYPE) -#define G_AOPEN_PKT_TYPE(x) (((x) >> S_AOPEN_PKT_TYPE) & M_AOPEN_PKT_TYPE) - -#define S_AOPEN_MAC_MATCH 14 -#define M_AOPEN_MAC_MATCH 0x1F -#define V_AOPEN_MAC_MATCH(x) ((x) << S_AOPEN_MAC_MATCH) -#define G_AOPEN_MAC_MATCH(x) (((x) >> S_AOPEN_MAC_MATCH) & M_AOPEN_MAC_MATCH) - -#define S_AOPEN_MAC_MATCH_VALID 19 -#define V_AOPEN_MAC_MATCH_VALID(x) ((x) << S_AOPEN_MAC_MATCH_VALID) -#define F_AOPEN_MAC_MATCH_VALID V_AOPEN_MAC_MATCH_VALID(1U) - -#define S_AOPEN_IFF_VLAN 20 -#define M_AOPEN_IFF_VLAN 0xFFF -#define V_AOPEN_IFF_VLAN(x) ((x) << S_AOPEN_IFF_VLAN) -#define G_AOPEN_IFF_VLAN(x) (((x) >> S_AOPEN_IFF_VLAN) & M_AOPEN_IFF_VLAN) - -struct cpl_act_open_rpl { - RSS_HDR union opcode_tid ot; - __be16 local_port; - __be16 peer_port; - __be32 local_ip; - __be32 peer_ip; - __be32 atid; - __u8 rsvd[3]; - __u8 status; -}; - -struct cpl_act_establish { - RSS_HDR union opcode_tid ot; - __be16 local_port; - __be16 peer_port; - __be32 local_ip; - __be32 peer_ip; - __be32 tos_tid; - __be16 l2t_idx; - __be16 tcp_opt; - __be32 snd_isn; - __be32 rcv_isn; -}; - -struct cpl_get_tcb { - WR_HDR; - union opcode_tid ot; - __be16 cpuno; - __be16 rsvd; -}; - -struct cpl_get_tcb_rpl { - RSS_HDR union opcode_tid ot; - __u8 rsvd; - __u8 status; - __be16 len; -}; - -struct cpl_set_tcb { - WR_HDR; - union opcode_tid ot; - __u8 reply; - __u8 cpu_idx; - __be16 len; -}; - -/* cpl_set_tcb.reply fields */ -#define S_NO_REPLY 7 -#define V_NO_REPLY(x) ((x) << S_NO_REPLY) -#define F_NO_REPLY V_NO_REPLY(1U) - -struct cpl_set_tcb_field { - WR_HDR; - union opcode_tid ot; - __u8 reply; - __u8 cpu_idx; - __be16 word; - __be64 mask; - __be64 val; -}; - -struct cpl_set_tcb_rpl { - RSS_HDR union opcode_tid ot; - __u8 rsvd[3]; - __u8 status; -}; - -struct cpl_pcmd { - WR_HDR; - union opcode_tid ot; - __u8 rsvd[3]; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 src:1; - __u8 bundle:1; - __u8 channel:1; - __u8:5; -#else - __u8:5; - __u8 channel:1; - __u8 bundle:1; - __u8 src:1; -#endif - __be32 pcmd_parm[2]; -}; - -struct cpl_pcmd_reply { - RSS_HDR union opcode_tid ot; - __u8 status; - __u8 rsvd; - __be16 len; -}; - -struct cpl_close_con_req { - WR_HDR; - union opcode_tid ot; - __be32 rsvd; -}; - -struct cpl_close_con_rpl { - RSS_HDR union opcode_tid ot; - __u8 rsvd[3]; - __u8 status; - __be32 snd_nxt; - __be32 rcv_nxt; -}; - -struct cpl_close_listserv_req { - WR_HDR; - union opcode_tid ot; - __u8 rsvd0; - __u8 cpu_idx; - __be16 rsvd1; -}; - -struct cpl_close_listserv_rpl { - RSS_HDR union opcode_tid ot; - __u8 rsvd[3]; - __u8 status; -}; - -struct cpl_abort_req_rss { - RSS_HDR union opcode_tid ot; - __be32 rsvd0; - __u8 rsvd1; - __u8 status; - __u8 rsvd2[6]; -}; - -struct cpl_abort_req { - WR_HDR; - union opcode_tid ot; - __be32 rsvd0; - __u8 rsvd1; - __u8 cmd; - __u8 rsvd2[6]; -}; - -struct cpl_abort_rpl_rss { - RSS_HDR union opcode_tid ot; - __be32 rsvd0; - __u8 rsvd1; - __u8 status; - __u8 rsvd2[6]; -}; - -struct cpl_abort_rpl { - WR_HDR; - union opcode_tid ot; - __be32 rsvd0; - __u8 rsvd1; - __u8 cmd; - __u8 rsvd2[6]; -}; - -struct cpl_peer_close { - RSS_HDR union opcode_tid ot; - __be32 rcv_nxt; -}; - -struct tx_data_wr { - __be32 wr_hi; - __be32 wr_lo; - __be32 len; - __be32 flags; - __be32 sndseq; - __be32 param; -}; - -/* tx_data_wr.param fields */ -#define S_TX_PORT 0 -#define M_TX_PORT 0x7 -#define V_TX_PORT(x) ((x) << S_TX_PORT) -#define G_TX_PORT(x) (((x) >> S_TX_PORT) & M_TX_PORT) - -#define S_TX_MSS 4 -#define M_TX_MSS 0xF -#define V_TX_MSS(x) ((x) << S_TX_MSS) -#define G_TX_MSS(x) (((x) >> S_TX_MSS) & M_TX_MSS) - -#define S_TX_QOS 8 -#define M_TX_QOS 0xFF -#define V_TX_QOS(x) ((x) << S_TX_QOS) -#define G_TX_QOS(x) (((x) >> S_TX_QOS) & M_TX_QOS) - -#define S_TX_SNDBUF 16 -#define M_TX_SNDBUF 0xFFFF -#define V_TX_SNDBUF(x) ((x) << S_TX_SNDBUF) -#define G_TX_SNDBUF(x) (((x) >> S_TX_SNDBUF) & M_TX_SNDBUF) - -struct cpl_tx_data { - union opcode_tid ot; - __be32 len; - __be32 rsvd; - __be16 urg; - __be16 flags; -}; - -/* cpl_tx_data.flags fields */ -#define S_TX_ULP_SUBMODE 6 -#define M_TX_ULP_SUBMODE 0xF -#define V_TX_ULP_SUBMODE(x) ((x) << S_TX_ULP_SUBMODE) -#define G_TX_ULP_SUBMODE(x) (((x) >> S_TX_ULP_SUBMODE) & M_TX_ULP_SUBMODE) - -#define S_TX_ULP_MODE 10 -#define M_TX_ULP_MODE 0xF -#define V_TX_ULP_MODE(x) ((x) << S_TX_ULP_MODE) -#define G_TX_ULP_MODE(x) (((x) >> S_TX_ULP_MODE) & M_TX_ULP_MODE) - -#define S_TX_SHOVE 14 -#define V_TX_SHOVE(x) ((x) << S_TX_SHOVE) -#define F_TX_SHOVE V_TX_SHOVE(1U) - -#define S_TX_MORE 15 -#define V_TX_MORE(x) ((x) << S_TX_MORE) -#define F_TX_MORE V_TX_MORE(1U) - -/* additional tx_data_wr.flags fields */ -#define S_TX_CPU_IDX 0 -#define M_TX_CPU_IDX 0x3F -#define V_TX_CPU_IDX(x) ((x) << S_TX_CPU_IDX) -#define G_TX_CPU_IDX(x) (((x) >> S_TX_CPU_IDX) & M_TX_CPU_IDX) - -#define S_TX_URG 16 -#define V_TX_URG(x) ((x) << S_TX_URG) -#define F_TX_URG V_TX_URG(1U) - -#define S_TX_CLOSE 17 -#define V_TX_CLOSE(x) ((x) << S_TX_CLOSE) -#define F_TX_CLOSE V_TX_CLOSE(1U) - -#define S_TX_INIT 18 -#define V_TX_INIT(x) ((x) << S_TX_INIT) -#define F_TX_INIT V_TX_INIT(1U) - -#define S_TX_IMM_ACK 19 -#define V_TX_IMM_ACK(x) ((x) << S_TX_IMM_ACK) -#define F_TX_IMM_ACK V_TX_IMM_ACK(1U) - -#define S_TX_IMM_DMA 20 -#define V_TX_IMM_DMA(x) ((x) << S_TX_IMM_DMA) -#define F_TX_IMM_DMA V_TX_IMM_DMA(1U) - -struct cpl_tx_data_ack { - RSS_HDR union opcode_tid ot; - __be32 ack_seq; -}; - -struct cpl_wr_ack { - RSS_HDR union opcode_tid ot; - __be16 credits; - __be16 rsvd; - __be32 snd_nxt; - __be32 snd_una; -}; - -struct cpl_rdma_ec_status { - RSS_HDR union opcode_tid ot; - __u8 rsvd[3]; - __u8 status; -}; - -struct mngt_pktsched_wr { - __be32 wr_hi; - __be32 wr_lo; - __u8 mngt_opcode; - __u8 rsvd[7]; - __u8 sched; - __u8 idx; - __u8 min; - __u8 max; - __u8 binding; - __u8 rsvd1[3]; -}; - -struct cpl_iscsi_hdr { - RSS_HDR union opcode_tid ot; - __be16 pdu_len_ddp; - __be16 len; - __be32 seq; - __be16 urg; - __u8 rsvd; - __u8 status; -}; - -/* cpl_iscsi_hdr.pdu_len_ddp fields */ -#define S_ISCSI_PDU_LEN 0 -#define M_ISCSI_PDU_LEN 0x7FFF -#define V_ISCSI_PDU_LEN(x) ((x) << S_ISCSI_PDU_LEN) -#define G_ISCSI_PDU_LEN(x) (((x) >> S_ISCSI_PDU_LEN) & M_ISCSI_PDU_LEN) - -#define S_ISCSI_DDP 15 -#define V_ISCSI_DDP(x) ((x) << S_ISCSI_DDP) -#define F_ISCSI_DDP V_ISCSI_DDP(1U) - -struct cpl_rx_data { - RSS_HDR union opcode_tid ot; - __be16 rsvd; - __be16 len; - __be32 seq; - __be16 urg; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 dack_mode:2; - __u8 psh:1; - __u8 heartbeat:1; - __u8:4; -#else - __u8:4; - __u8 heartbeat:1; - __u8 psh:1; - __u8 dack_mode:2; -#endif - __u8 status; -}; - -struct cpl_rx_data_ack { - WR_HDR; - union opcode_tid ot; - __be32 credit_dack; -}; - -/* cpl_rx_data_ack.ack_seq fields */ -#define S_RX_CREDITS 0 -#define M_RX_CREDITS 0x7FFFFFF -#define V_RX_CREDITS(x) ((x) << S_RX_CREDITS) -#define G_RX_CREDITS(x) (((x) >> S_RX_CREDITS) & M_RX_CREDITS) - -#define S_RX_MODULATE 27 -#define V_RX_MODULATE(x) ((x) << S_RX_MODULATE) -#define F_RX_MODULATE V_RX_MODULATE(1U) - -#define S_RX_FORCE_ACK 28 -#define V_RX_FORCE_ACK(x) ((x) << S_RX_FORCE_ACK) -#define F_RX_FORCE_ACK V_RX_FORCE_ACK(1U) - -#define S_RX_DACK_MODE 29 -#define M_RX_DACK_MODE 0x3 -#define V_RX_DACK_MODE(x) ((x) << S_RX_DACK_MODE) -#define G_RX_DACK_MODE(x) (((x) >> S_RX_DACK_MODE) & M_RX_DACK_MODE) - -#define S_RX_DACK_CHANGE 31 -#define V_RX_DACK_CHANGE(x) ((x) << S_RX_DACK_CHANGE) -#define F_RX_DACK_CHANGE V_RX_DACK_CHANGE(1U) - -struct cpl_rx_urg_notify { - RSS_HDR union opcode_tid ot; - __be32 seq; -}; - -struct cpl_rx_ddp_complete { - RSS_HDR union opcode_tid ot; - __be32 ddp_report; -}; - -struct cpl_rx_data_ddp { - RSS_HDR union opcode_tid ot; - __be16 urg; - __be16 len; - __be32 seq; - union { - __be32 nxt_seq; - __be32 ddp_report; - }; - __be32 ulp_crc; - __be32 ddpvld_status; -}; - -/* cpl_rx_data_ddp.ddpvld_status fields */ -#define S_DDP_STATUS 0 -#define M_DDP_STATUS 0xFF -#define V_DDP_STATUS(x) ((x) << S_DDP_STATUS) -#define G_DDP_STATUS(x) (((x) >> S_DDP_STATUS) & M_DDP_STATUS) - -#define S_DDP_VALID 15 -#define M_DDP_VALID 0x1FFFF -#define V_DDP_VALID(x) ((x) << S_DDP_VALID) -#define G_DDP_VALID(x) (((x) >> S_DDP_VALID) & M_DDP_VALID) - -#define S_DDP_PPOD_MISMATCH 15 -#define V_DDP_PPOD_MISMATCH(x) ((x) << S_DDP_PPOD_MISMATCH) -#define F_DDP_PPOD_MISMATCH V_DDP_PPOD_MISMATCH(1U) - -#define S_DDP_PDU 16 -#define V_DDP_PDU(x) ((x) << S_DDP_PDU) -#define F_DDP_PDU V_DDP_PDU(1U) - -#define S_DDP_LLIMIT_ERR 17 -#define V_DDP_LLIMIT_ERR(x) ((x) << S_DDP_LLIMIT_ERR) -#define F_DDP_LLIMIT_ERR V_DDP_LLIMIT_ERR(1U) - -#define S_DDP_PPOD_PARITY_ERR 18 -#define V_DDP_PPOD_PARITY_ERR(x) ((x) << S_DDP_PPOD_PARITY_ERR) -#define F_DDP_PPOD_PARITY_ERR V_DDP_PPOD_PARITY_ERR(1U) - -#define S_DDP_PADDING_ERR 19 -#define V_DDP_PADDING_ERR(x) ((x) << S_DDP_PADDING_ERR) -#define F_DDP_PADDING_ERR V_DDP_PADDING_ERR(1U) - -#define S_DDP_HDRCRC_ERR 20 -#define V_DDP_HDRCRC_ERR(x) ((x) << S_DDP_HDRCRC_ERR) -#define F_DDP_HDRCRC_ERR V_DDP_HDRCRC_ERR(1U) - -#define S_DDP_DATACRC_ERR 21 -#define V_DDP_DATACRC_ERR(x) ((x) << S_DDP_DATACRC_ERR) -#define F_DDP_DATACRC_ERR V_DDP_DATACRC_ERR(1U) - -#define S_DDP_INVALID_TAG 22 -#define V_DDP_INVALID_TAG(x) ((x) << S_DDP_INVALID_TAG) -#define F_DDP_INVALID_TAG V_DDP_INVALID_TAG(1U) - -#define S_DDP_ULIMIT_ERR 23 -#define V_DDP_ULIMIT_ERR(x) ((x) << S_DDP_ULIMIT_ERR) -#define F_DDP_ULIMIT_ERR V_DDP_ULIMIT_ERR(1U) - -#define S_DDP_OFFSET_ERR 24 -#define V_DDP_OFFSET_ERR(x) ((x) << S_DDP_OFFSET_ERR) -#define F_DDP_OFFSET_ERR V_DDP_OFFSET_ERR(1U) - -#define S_DDP_COLOR_ERR 25 -#define V_DDP_COLOR_ERR(x) ((x) << S_DDP_COLOR_ERR) -#define F_DDP_COLOR_ERR V_DDP_COLOR_ERR(1U) - -#define S_DDP_TID_MISMATCH 26 -#define V_DDP_TID_MISMATCH(x) ((x) << S_DDP_TID_MISMATCH) -#define F_DDP_TID_MISMATCH V_DDP_TID_MISMATCH(1U) - -#define S_DDP_INVALID_PPOD 27 -#define V_DDP_INVALID_PPOD(x) ((x) << S_DDP_INVALID_PPOD) -#define F_DDP_INVALID_PPOD V_DDP_INVALID_PPOD(1U) - -#define S_DDP_ULP_MODE 28 -#define M_DDP_ULP_MODE 0xF -#define V_DDP_ULP_MODE(x) ((x) << S_DDP_ULP_MODE) -#define G_DDP_ULP_MODE(x) (((x) >> S_DDP_ULP_MODE) & M_DDP_ULP_MODE) - -/* cpl_rx_data_ddp.ddp_report fields */ -#define S_DDP_OFFSET 0 -#define M_DDP_OFFSET 0x3FFFFF -#define V_DDP_OFFSET(x) ((x) << S_DDP_OFFSET) -#define G_DDP_OFFSET(x) (((x) >> S_DDP_OFFSET) & M_DDP_OFFSET) - -#define S_DDP_URG 24 -#define V_DDP_URG(x) ((x) << S_DDP_URG) -#define F_DDP_URG V_DDP_URG(1U) - -#define S_DDP_PSH 25 -#define V_DDP_PSH(x) ((x) << S_DDP_PSH) -#define F_DDP_PSH V_DDP_PSH(1U) - -#define S_DDP_BUF_COMPLETE 26 -#define V_DDP_BUF_COMPLETE(x) ((x) << S_DDP_BUF_COMPLETE) -#define F_DDP_BUF_COMPLETE V_DDP_BUF_COMPLETE(1U) - -#define S_DDP_BUF_TIMED_OUT 27 -#define V_DDP_BUF_TIMED_OUT(x) ((x) << S_DDP_BUF_TIMED_OUT) -#define F_DDP_BUF_TIMED_OUT V_DDP_BUF_TIMED_OUT(1U) - -#define S_DDP_BUF_IDX 28 -#define V_DDP_BUF_IDX(x) ((x) << S_DDP_BUF_IDX) -#define F_DDP_BUF_IDX V_DDP_BUF_IDX(1U) - -struct cpl_tx_pkt { - WR_HDR; - __be32 cntrl; - __be32 len; -}; - -struct cpl_tx_pkt_lso { - WR_HDR; - __be32 cntrl; - __be32 len; - - __be32 rsvd; - __be32 lso_info; -}; - -/* cpl_tx_pkt*.cntrl fields */ -#define S_TXPKT_VLAN 0 -#define M_TXPKT_VLAN 0xFFFF -#define V_TXPKT_VLAN(x) ((x) << S_TXPKT_VLAN) -#define G_TXPKT_VLAN(x) (((x) >> S_TXPKT_VLAN) & M_TXPKT_VLAN) - -#define S_TXPKT_INTF 16 -#define M_TXPKT_INTF 0xF -#define V_TXPKT_INTF(x) ((x) << S_TXPKT_INTF) -#define G_TXPKT_INTF(x) (((x) >> S_TXPKT_INTF) & M_TXPKT_INTF) - -#define S_TXPKT_IPCSUM_DIS 20 -#define V_TXPKT_IPCSUM_DIS(x) ((x) << S_TXPKT_IPCSUM_DIS) -#define F_TXPKT_IPCSUM_DIS V_TXPKT_IPCSUM_DIS(1U) - -#define S_TXPKT_L4CSUM_DIS 21 -#define V_TXPKT_L4CSUM_DIS(x) ((x) << S_TXPKT_L4CSUM_DIS) -#define F_TXPKT_L4CSUM_DIS V_TXPKT_L4CSUM_DIS(1U) - -#define S_TXPKT_VLAN_VLD 22 -#define V_TXPKT_VLAN_VLD(x) ((x) << S_TXPKT_VLAN_VLD) -#define F_TXPKT_VLAN_VLD V_TXPKT_VLAN_VLD(1U) - -#define S_TXPKT_LOOPBACK 23 -#define V_TXPKT_LOOPBACK(x) ((x) << S_TXPKT_LOOPBACK) -#define F_TXPKT_LOOPBACK V_TXPKT_LOOPBACK(1U) - -#define S_TXPKT_OPCODE 24 -#define M_TXPKT_OPCODE 0xFF -#define V_TXPKT_OPCODE(x) ((x) << S_TXPKT_OPCODE) -#define G_TXPKT_OPCODE(x) (((x) >> S_TXPKT_OPCODE) & M_TXPKT_OPCODE) - -/* cpl_tx_pkt_lso.lso_info fields */ -#define S_LSO_MSS 0 -#define M_LSO_MSS 0x3FFF -#define V_LSO_MSS(x) ((x) << S_LSO_MSS) -#define G_LSO_MSS(x) (((x) >> S_LSO_MSS) & M_LSO_MSS) - -#define S_LSO_ETH_TYPE 14 -#define M_LSO_ETH_TYPE 0x3 -#define V_LSO_ETH_TYPE(x) ((x) << S_LSO_ETH_TYPE) -#define G_LSO_ETH_TYPE(x) (((x) >> S_LSO_ETH_TYPE) & M_LSO_ETH_TYPE) - -#define S_LSO_TCPHDR_WORDS 16 -#define M_LSO_TCPHDR_WORDS 0xF -#define V_LSO_TCPHDR_WORDS(x) ((x) << S_LSO_TCPHDR_WORDS) -#define G_LSO_TCPHDR_WORDS(x) (((x) >> S_LSO_TCPHDR_WORDS) & M_LSO_TCPHDR_WORDS) - -#define S_LSO_IPHDR_WORDS 20 -#define M_LSO_IPHDR_WORDS 0xF -#define V_LSO_IPHDR_WORDS(x) ((x) << S_LSO_IPHDR_WORDS) -#define G_LSO_IPHDR_WORDS(x) (((x) >> S_LSO_IPHDR_WORDS) & M_LSO_IPHDR_WORDS) - -#define S_LSO_IPV6 24 -#define V_LSO_IPV6(x) ((x) << S_LSO_IPV6) -#define F_LSO_IPV6 V_LSO_IPV6(1U) - -struct cpl_trace_pkt { -#ifdef CHELSIO_FW - __u8 rss_opcode; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 err:1; - __u8:7; -#else - __u8:7; - __u8 err:1; -#endif - __u8 rsvd0; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 qid:4; - __u8:4; -#else - __u8:4; - __u8 qid:4; -#endif - __be32 tstamp; -#endif /* CHELSIO_FW */ - - __u8 opcode; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 iff:4; - __u8:4; -#else - __u8:4; - __u8 iff:4; -#endif - __u8 rsvd[4]; - __be16 len; -}; - -struct cpl_rx_pkt { - RSS_HDR __u8 opcode; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 iff:4; - __u8 csum_valid:1; - __u8 ipmi_pkt:1; - __u8 vlan_valid:1; - __u8 fragment:1; -#else - __u8 fragment:1; - __u8 vlan_valid:1; - __u8 ipmi_pkt:1; - __u8 csum_valid:1; - __u8 iff:4; -#endif - __be16 csum; - __be16 vlan; - __be16 len; -}; - -struct cpl_l2t_write_req { - WR_HDR; - union opcode_tid ot; - __be32 params; - __u8 rsvd[2]; - __u8 dst_mac[6]; -}; - -/* cpl_l2t_write_req.params fields */ -#define S_L2T_W_IDX 0 -#define M_L2T_W_IDX 0x7FF -#define V_L2T_W_IDX(x) ((x) << S_L2T_W_IDX) -#define G_L2T_W_IDX(x) (((x) >> S_L2T_W_IDX) & M_L2T_W_IDX) - -#define S_L2T_W_VLAN 11 -#define M_L2T_W_VLAN 0xFFF -#define V_L2T_W_VLAN(x) ((x) << S_L2T_W_VLAN) -#define G_L2T_W_VLAN(x) (((x) >> S_L2T_W_VLAN) & M_L2T_W_VLAN) - -#define S_L2T_W_IFF 23 -#define M_L2T_W_IFF 0xF -#define V_L2T_W_IFF(x) ((x) << S_L2T_W_IFF) -#define G_L2T_W_IFF(x) (((x) >> S_L2T_W_IFF) & M_L2T_W_IFF) - -#define S_L2T_W_PRIO 27 -#define M_L2T_W_PRIO 0x7 -#define V_L2T_W_PRIO(x) ((x) << S_L2T_W_PRIO) -#define G_L2T_W_PRIO(x) (((x) >> S_L2T_W_PRIO) & M_L2T_W_PRIO) - -struct cpl_l2t_write_rpl { - RSS_HDR union opcode_tid ot; - __u8 status; - __u8 rsvd[3]; -}; - -struct cpl_l2t_read_req { - WR_HDR; - union opcode_tid ot; - __be16 rsvd; - __be16 l2t_idx; -}; - -struct cpl_l2t_read_rpl { - RSS_HDR union opcode_tid ot; - __be32 params; - __u8 rsvd[2]; - __u8 dst_mac[6]; -}; - -/* cpl_l2t_read_rpl.params fields */ -#define S_L2T_R_PRIO 0 -#define M_L2T_R_PRIO 0x7 -#define V_L2T_R_PRIO(x) ((x) << S_L2T_R_PRIO) -#define G_L2T_R_PRIO(x) (((x) >> S_L2T_R_PRIO) & M_L2T_R_PRIO) - -#define S_L2T_R_VLAN 8 -#define M_L2T_R_VLAN 0xFFF -#define V_L2T_R_VLAN(x) ((x) << S_L2T_R_VLAN) -#define G_L2T_R_VLAN(x) (((x) >> S_L2T_R_VLAN) & M_L2T_R_VLAN) - -#define S_L2T_R_IFF 20 -#define M_L2T_R_IFF 0xF -#define V_L2T_R_IFF(x) ((x) << S_L2T_R_IFF) -#define G_L2T_R_IFF(x) (((x) >> S_L2T_R_IFF) & M_L2T_R_IFF) - -#define S_L2T_STATUS 24 -#define M_L2T_STATUS 0xFF -#define V_L2T_STATUS(x) ((x) << S_L2T_STATUS) -#define G_L2T_STATUS(x) (((x) >> S_L2T_STATUS) & M_L2T_STATUS) - -struct cpl_smt_write_req { - WR_HDR; - union opcode_tid ot; - __u8 rsvd0; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 mtu_idx:4; - __u8 iff:4; -#else - __u8 iff:4; - __u8 mtu_idx:4; -#endif - __be16 rsvd2; - __be16 rsvd3; - __u8 src_mac1[6]; - __be16 rsvd4; - __u8 src_mac0[6]; -}; - -struct cpl_smt_write_rpl { - RSS_HDR union opcode_tid ot; - __u8 status; - __u8 rsvd[3]; -}; - -struct cpl_smt_read_req { - WR_HDR; - union opcode_tid ot; - __u8 rsvd0; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8:4; - __u8 iff:4; -#else - __u8 iff:4; - __u8:4; -#endif - __be16 rsvd2; -}; - -struct cpl_smt_read_rpl { - RSS_HDR union opcode_tid ot; - __u8 status; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 mtu_idx:4; - __u8:4; -#else - __u8:4; - __u8 mtu_idx:4; -#endif - __be16 rsvd2; - __be16 rsvd3; - __u8 src_mac1[6]; - __be16 rsvd4; - __u8 src_mac0[6]; -}; - -struct cpl_rte_delete_req { - WR_HDR; - union opcode_tid ot; - __be32 params; -}; - -/* { cpl_rte_delete_req, cpl_rte_read_req }.params fields */ -#define S_RTE_REQ_LUT_IX 8 -#define M_RTE_REQ_LUT_IX 0x7FF -#define V_RTE_REQ_LUT_IX(x) ((x) << S_RTE_REQ_LUT_IX) -#define G_RTE_REQ_LUT_IX(x) (((x) >> S_RTE_REQ_LUT_IX) & M_RTE_REQ_LUT_IX) - -#define S_RTE_REQ_LUT_BASE 19 -#define M_RTE_REQ_LUT_BASE 0x7FF -#define V_RTE_REQ_LUT_BASE(x) ((x) << S_RTE_REQ_LUT_BASE) -#define G_RTE_REQ_LUT_BASE(x) (((x) >> S_RTE_REQ_LUT_BASE) & M_RTE_REQ_LUT_BASE) - -#define S_RTE_READ_REQ_SELECT 31 -#define V_RTE_READ_REQ_SELECT(x) ((x) << S_RTE_READ_REQ_SELECT) -#define F_RTE_READ_REQ_SELECT V_RTE_READ_REQ_SELECT(1U) - -struct cpl_rte_delete_rpl { - RSS_HDR union opcode_tid ot; - __u8 status; - __u8 rsvd[3]; -}; - -struct cpl_rte_write_req { - WR_HDR; - union opcode_tid ot; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8:6; - __u8 write_tcam:1; - __u8 write_l2t_lut:1; -#else - __u8 write_l2t_lut:1; - __u8 write_tcam:1; - __u8:6; -#endif - __u8 rsvd[3]; - __be32 lut_params; - __be16 rsvd2; - __be16 l2t_idx; - __be32 netmask; - __be32 faddr; -}; - -/* cpl_rte_write_req.lut_params fields */ -#define S_RTE_WRITE_REQ_LUT_IX 10 -#define M_RTE_WRITE_REQ_LUT_IX 0x7FF -#define V_RTE_WRITE_REQ_LUT_IX(x) ((x) << S_RTE_WRITE_REQ_LUT_IX) -#define G_RTE_WRITE_REQ_LUT_IX(x) (((x) >> S_RTE_WRITE_REQ_LUT_IX) & M_RTE_WRITE_REQ_LUT_IX) - -#define S_RTE_WRITE_REQ_LUT_BASE 21 -#define M_RTE_WRITE_REQ_LUT_BASE 0x7FF -#define V_RTE_WRITE_REQ_LUT_BASE(x) ((x) << S_RTE_WRITE_REQ_LUT_BASE) -#define G_RTE_WRITE_REQ_LUT_BASE(x) (((x) >> S_RTE_WRITE_REQ_LUT_BASE) & M_RTE_WRITE_REQ_LUT_BASE) - -struct cpl_rte_write_rpl { - RSS_HDR union opcode_tid ot; - __u8 status; - __u8 rsvd[3]; -}; - -struct cpl_rte_read_req { - WR_HDR; - union opcode_tid ot; - __be32 params; -}; - -struct cpl_rte_read_rpl { - RSS_HDR union opcode_tid ot; - __u8 status; - __u8 rsvd0; - __be16 l2t_idx; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8:7; - __u8 select:1; -#else - __u8 select:1; - __u8:7; -#endif - __u8 rsvd2[3]; - __be32 addr; -}; - -struct cpl_tid_release { - WR_HDR; - union opcode_tid ot; - __be32 rsvd; -}; - -struct cpl_barrier { - WR_HDR; - __u8 opcode; - __u8 rsvd[7]; -}; - -struct cpl_rdma_read_req { - __u8 opcode; - __u8 rsvd[15]; -}; - -struct cpl_rdma_terminate { -#ifdef CHELSIO_FW - __u8 opcode; - __u8 rsvd[2]; -#if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 rspq:3; - __u8:5; -#else - __u8:5; - __u8 rspq:3; -#endif - __be32 tid_len; -#endif - __be32 msn; - __be32 mo; - __u8 data[0]; -}; - -/* cpl_rdma_terminate.tid_len fields */ -#define S_FLIT_CNT 0 -#define M_FLIT_CNT 0xFF -#define V_FLIT_CNT(x) ((x) << S_FLIT_CNT) -#define G_FLIT_CNT(x) (((x) >> S_FLIT_CNT) & M_FLIT_CNT) - -#define S_TERM_TID 8 -#define M_TERM_TID 0xFFFFF -#define V_TERM_TID(x) ((x) << S_TERM_TID) -#define G_TERM_TID(x) (((x) >> S_TERM_TID) & M_TERM_TID) -#endif /* T3_CPL_H */ diff --git a/trunk/drivers/net/cxgb3/t3_hw.c b/trunk/drivers/net/cxgb3/t3_hw.c deleted file mode 100644 index 365a7f5b1f94..000000000000 --- a/trunk/drivers/net/cxgb3/t3_hw.c +++ /dev/null @@ -1,3375 +0,0 @@ -/* - * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "common.h" -#include "regs.h" -#include "sge_defs.h" -#include "firmware_exports.h" - -/** - * t3_wait_op_done_val - wait until an operation is completed - * @adapter: the adapter performing the operation - * @reg: the register to check for completion - * @mask: a single-bit field within @reg that indicates completion - * @polarity: the value of the field when the operation is completed - * @attempts: number of check iterations - * @delay: delay in usecs between iterations - * @valp: where to store the value of the register at completion time - * - * Wait until an operation is completed by checking a bit in a register - * up to @attempts times. If @valp is not NULL the value of the register - * at the time it indicated completion is stored there. Returns 0 if the - * operation completes and -EAGAIN otherwise. - */ - -int t3_wait_op_done_val(struct adapter *adapter, int reg, u32 mask, - int polarity, int attempts, int delay, u32 *valp) -{ - while (1) { - u32 val = t3_read_reg(adapter, reg); - - if (!!(val & mask) == polarity) { - if (valp) - *valp = val; - return 0; - } - if (--attempts == 0) - return -EAGAIN; - if (delay) - udelay(delay); - } -} - -/** - * t3_write_regs - write a bunch of registers - * @adapter: the adapter to program - * @p: an array of register address/register value pairs - * @n: the number of address/value pairs - * @offset: register address offset - * - * Takes an array of register address/register value pairs and writes each - * value to the corresponding register. Register addresses are adjusted - * by the supplied offset. - */ -void t3_write_regs(struct adapter *adapter, const struct addr_val_pair *p, - int n, unsigned int offset) -{ - while (n--) { - t3_write_reg(adapter, p->reg_addr + offset, p->val); - p++; - } -} - -/** - * t3_set_reg_field - set a register field to a value - * @adapter: the adapter to program - * @addr: the register address - * @mask: specifies the portion of the register to modify - * @val: the new value for the register field - * - * Sets a register field specified by the supplied mask to the - * given value. - */ -void t3_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask, - u32 val) -{ - u32 v = t3_read_reg(adapter, addr) & ~mask; - - t3_write_reg(adapter, addr, v | val); - t3_read_reg(adapter, addr); /* flush */ -} - -/** - * t3_read_indirect - read indirectly addressed registers - * @adap: the adapter - * @addr_reg: register holding the indirect address - * @data_reg: register holding the value of the indirect register - * @vals: where the read register values are stored - * @start_idx: index of first indirect register to read - * @nregs: how many indirect registers to read - * - * Reads registers that are accessed indirectly through an address/data - * register pair. - */ -void t3_read_indirect(struct adapter *adap, unsigned int addr_reg, - unsigned int data_reg, u32 *vals, unsigned int nregs, - unsigned int start_idx) -{ - while (nregs--) { - t3_write_reg(adap, addr_reg, start_idx); - *vals++ = t3_read_reg(adap, data_reg); - start_idx++; - } -} - -/** - * t3_mc7_bd_read - read from MC7 through backdoor accesses - * @mc7: identifies MC7 to read from - * @start: index of first 64-bit word to read - * @n: number of 64-bit words to read - * @buf: where to store the read result - * - * Read n 64-bit words from MC7 starting at word start, using backdoor - * accesses. - */ -int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n, - u64 *buf) -{ - static const int shift[] = { 0, 0, 16, 24 }; - static const int step[] = { 0, 32, 16, 8 }; - - unsigned int size64 = mc7->size / 8; /* # of 64-bit words */ - struct adapter *adap = mc7->adapter; - - if (start >= size64 || start + n > size64) - return -EINVAL; - - start *= (8 << mc7->width); - while (n--) { - int i; - u64 val64 = 0; - - for (i = (1 << mc7->width) - 1; i >= 0; --i) { - int attempts = 10; - u32 val; - - t3_write_reg(adap, mc7->offset + A_MC7_BD_ADDR, start); - t3_write_reg(adap, mc7->offset + A_MC7_BD_OP, 0); - val = t3_read_reg(adap, mc7->offset + A_MC7_BD_OP); - while ((val & F_BUSY) && attempts--) - val = t3_read_reg(adap, - mc7->offset + A_MC7_BD_OP); - if (val & F_BUSY) - return -EIO; - - val = t3_read_reg(adap, mc7->offset + A_MC7_BD_DATA1); - if (mc7->width == 0) { - val64 = t3_read_reg(adap, - mc7->offset + - A_MC7_BD_DATA0); - val64 |= (u64) val << 32; - } else { - if (mc7->width > 1) - val >>= shift[mc7->width]; - val64 |= (u64) val << (step[mc7->width] * i); - } - start += 8; - } - *buf++ = val64; - } - return 0; -} - -/* - * Initialize MI1. - */ -static void mi1_init(struct adapter *adap, const struct adapter_info *ai) -{ - u32 clkdiv = adap->params.vpd.cclk / (2 * adap->params.vpd.mdc) - 1; - u32 val = F_PREEN | V_MDIINV(ai->mdiinv) | V_MDIEN(ai->mdien) | - V_CLKDIV(clkdiv); - - if (!(ai->caps & SUPPORTED_10000baseT_Full)) - val |= V_ST(1); - t3_write_reg(adap, A_MI1_CFG, val); -} - -#define MDIO_ATTEMPTS 10 - -/* - * MI1 read/write operations for direct-addressed PHYs. - */ -static int mi1_read(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) -{ - int ret; - u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); - - if (mmd_addr) - return -EINVAL; - - mutex_lock(&adapter->mdio_lock); - t3_write_reg(adapter, A_MI1_ADDR, addr); - t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2)); - ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); - if (!ret) - *valp = t3_read_reg(adapter, A_MI1_DATA); - mutex_unlock(&adapter->mdio_lock); - return ret; -} - -static int mi1_write(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) -{ - int ret; - u32 addr = V_REGADDR(reg_addr) | V_PHYADDR(phy_addr); - - if (mmd_addr) - return -EINVAL; - - mutex_lock(&adapter->mdio_lock); - t3_write_reg(adapter, A_MI1_ADDR, addr); - t3_write_reg(adapter, A_MI1_DATA, val); - t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); - ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); - mutex_unlock(&adapter->mdio_lock); - return ret; -} - -static const struct mdio_ops mi1_mdio_ops = { - mi1_read, - mi1_write -}; - -/* - * MI1 read/write operations for indirect-addressed PHYs. - */ -static int mi1_ext_read(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int *valp) -{ - int ret; - u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr); - - mutex_lock(&adapter->mdio_lock); - t3_write_reg(adapter, A_MI1_ADDR, addr); - t3_write_reg(adapter, A_MI1_DATA, reg_addr); - t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0)); - ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); - if (!ret) { - t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3)); - ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, - MDIO_ATTEMPTS, 20); - if (!ret) - *valp = t3_read_reg(adapter, A_MI1_DATA); - } - mutex_unlock(&adapter->mdio_lock); - return ret; -} - -static int mi1_ext_write(struct adapter *adapter, int phy_addr, int mmd_addr, - int reg_addr, unsigned int val) -{ - int ret; - u32 addr = V_REGADDR(mmd_addr) | V_PHYADDR(phy_addr); - - mutex_lock(&adapter->mdio_lock); - t3_write_reg(adapter, A_MI1_ADDR, addr); - t3_write_reg(adapter, A_MI1_DATA, reg_addr); - t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0)); - ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20); - if (!ret) { - t3_write_reg(adapter, A_MI1_DATA, val); - t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1)); - ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, - MDIO_ATTEMPTS, 20); - } - mutex_unlock(&adapter->mdio_lock); - return ret; -} - -static const struct mdio_ops mi1_mdio_ext_ops = { - mi1_ext_read, - mi1_ext_write -}; - -/** - * t3_mdio_change_bits - modify the value of a PHY register - * @phy: the PHY to operate on - * @mmd: the device address - * @reg: the register address - * @clear: what part of the register value to mask off - * @set: what part of the register value to set - * - * Changes the value of a PHY register by applying a mask to its current - * value and ORing the result with a new value. - */ -int t3_mdio_change_bits(struct cphy *phy, int mmd, int reg, unsigned int clear, - unsigned int set) -{ - int ret; - unsigned int val; - - ret = mdio_read(phy, mmd, reg, &val); - if (!ret) { - val &= ~clear; - ret = mdio_write(phy, mmd, reg, val | set); - } - return ret; -} - -/** - * t3_phy_reset - reset a PHY block - * @phy: the PHY to operate on - * @mmd: the device address of the PHY block to reset - * @wait: how long to wait for the reset to complete in 1ms increments - * - * Resets a PHY block and optionally waits for the reset to complete. - * @mmd should be 0 for 10/100/1000 PHYs and the device address to reset - * for 10G PHYs. - */ -int t3_phy_reset(struct cphy *phy, int mmd, int wait) -{ - int err; - unsigned int ctl; - - err = t3_mdio_change_bits(phy, mmd, MII_BMCR, BMCR_PDOWN, BMCR_RESET); - if (err || !wait) - return err; - - do { - err = mdio_read(phy, mmd, MII_BMCR, &ctl); - if (err) - return err; - ctl &= BMCR_RESET; - if (ctl) - msleep(1); - } while (ctl && --wait); - - return ctl ? -1 : 0; -} - -/** - * t3_phy_advertise - set the PHY advertisement registers for autoneg - * @phy: the PHY to operate on - * @advert: bitmap of capabilities the PHY should advertise - * - * Sets a 10/100/1000 PHY's advertisement registers to advertise the - * requested capabilities. - */ -int t3_phy_advertise(struct cphy *phy, unsigned int advert) -{ - int err; - unsigned int val = 0; - - err = mdio_read(phy, 0, MII_CTRL1000, &val); - if (err) - return err; - - val &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - if (advert & ADVERTISED_1000baseT_Half) - val |= ADVERTISE_1000HALF; - if (advert & ADVERTISED_1000baseT_Full) - val |= ADVERTISE_1000FULL; - - err = mdio_write(phy, 0, MII_CTRL1000, val); - if (err) - return err; - - val = 1; - if (advert & ADVERTISED_10baseT_Half) - val |= ADVERTISE_10HALF; - if (advert & ADVERTISED_10baseT_Full) - val |= ADVERTISE_10FULL; - if (advert & ADVERTISED_100baseT_Half) - val |= ADVERTISE_100HALF; - if (advert & ADVERTISED_100baseT_Full) - val |= ADVERTISE_100FULL; - if (advert & ADVERTISED_Pause) - val |= ADVERTISE_PAUSE_CAP; - if (advert & ADVERTISED_Asym_Pause) - val |= ADVERTISE_PAUSE_ASYM; - return mdio_write(phy, 0, MII_ADVERTISE, val); -} - -/** - * t3_set_phy_speed_duplex - force PHY speed and duplex - * @phy: the PHY to operate on - * @speed: requested PHY speed - * @duplex: requested PHY duplex - * - * Force a 10/100/1000 PHY's speed and duplex. This also disables - * auto-negotiation except for GigE, where auto-negotiation is mandatory. - */ -int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex) -{ - int err; - unsigned int ctl; - - err = mdio_read(phy, 0, MII_BMCR, &ctl); - if (err) - return err; - - if (speed >= 0) { - ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE); - if (speed == SPEED_100) - ctl |= BMCR_SPEED100; - else if (speed == SPEED_1000) - ctl |= BMCR_SPEED1000; - } - if (duplex >= 0) { - ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE); - if (duplex == DUPLEX_FULL) - ctl |= BMCR_FULLDPLX; - } - if (ctl & BMCR_SPEED1000) /* auto-negotiation required for GigE */ - ctl |= BMCR_ANENABLE; - return mdio_write(phy, 0, MII_BMCR, ctl); -} - -static const struct adapter_info t3_adap_info[] = { - {2, 0, 0, 0, - F_GPIO2_OEN | F_GPIO4_OEN | - F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, - SUPPORTED_OFFLOAD, - &mi1_mdio_ops, "Chelsio PE9000"}, - {2, 0, 0, 0, - F_GPIO2_OEN | F_GPIO4_OEN | - F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5, - SUPPORTED_OFFLOAD, - &mi1_mdio_ops, "Chelsio T302"}, - {1, 0, 0, 0, - F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN | - F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, - SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD, - &mi1_mdio_ext_ops, "Chelsio T310"}, - {2, 0, 0, 0, - F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN | - F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL | - F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0, - SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_OFFLOAD, - &mi1_mdio_ext_ops, "Chelsio T320"}, -}; - -/* - * Return the adapter_info structure with a given index. Out-of-range indices - * return NULL. - */ -const struct adapter_info *t3_get_adapter_info(unsigned int id) -{ - return id < ARRAY_SIZE(t3_adap_info) ? &t3_adap_info[id] : NULL; -} - -#define CAPS_1G (SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full | \ - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII) -#define CAPS_10G (SUPPORTED_10000baseT_Full | SUPPORTED_AUI) - -static const struct port_type_info port_types[] = { - {NULL}, - {t3_ael1002_phy_prep, CAPS_10G | SUPPORTED_FIBRE, - "10GBASE-XR"}, - {t3_vsc8211_phy_prep, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ, - "10/100/1000BASE-T"}, - {NULL, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ, - "10/100/1000BASE-T"}, - {t3_xaui_direct_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, - {NULL, CAPS_10G, "10GBASE-KX4"}, - {t3_qt2045_phy_prep, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, - {t3_ael1006_phy_prep, CAPS_10G | SUPPORTED_FIBRE, - "10GBASE-SR"}, - {NULL, CAPS_10G | SUPPORTED_TP, "10GBASE-CX4"}, -}; - -#undef CAPS_1G -#undef CAPS_10G - -#define VPD_ENTRY(name, len) \ - u8 name##_kword[2]; u8 name##_len; u8 name##_data[len] - -/* - * Partial EEPROM Vital Product Data structure. Includes only the ID and - * VPD-R sections. - */ -struct t3_vpd { - u8 id_tag; - u8 id_len[2]; - u8 id_data[16]; - u8 vpdr_tag; - u8 vpdr_len[2]; - VPD_ENTRY(pn, 16); /* part number */ - VPD_ENTRY(ec, 16); /* EC level */ - VPD_ENTRY(sn, 16); /* serial number */ - VPD_ENTRY(na, 12); /* MAC address base */ - VPD_ENTRY(cclk, 6); /* core clock */ - VPD_ENTRY(mclk, 6); /* mem clock */ - VPD_ENTRY(uclk, 6); /* uP clk */ - VPD_ENTRY(mdc, 6); /* MDIO clk */ - VPD_ENTRY(mt, 2); /* mem timing */ - VPD_ENTRY(xaui0cfg, 6); /* XAUI0 config */ - VPD_ENTRY(xaui1cfg, 6); /* XAUI1 config */ - VPD_ENTRY(port0, 2); /* PHY0 complex */ - VPD_ENTRY(port1, 2); /* PHY1 complex */ - VPD_ENTRY(port2, 2); /* PHY2 complex */ - VPD_ENTRY(port3, 2); /* PHY3 complex */ - VPD_ENTRY(rv, 1); /* csum */ - u32 pad; /* for multiple-of-4 sizing and alignment */ -}; - -#define EEPROM_MAX_POLL 4 -#define EEPROM_STAT_ADDR 0x4000 -#define VPD_BASE 0xc00 - -/** - * t3_seeprom_read - read a VPD EEPROM location - * @adapter: adapter to read - * @addr: EEPROM address - * @data: where to store the read data - * - * Read a 32-bit word from a location in VPD EEPROM using the card's PCI - * VPD ROM capability. A zero is written to the flag bit when the - * addres is written to the control register. The hardware device will - * set the flag to 1 when 4 bytes have been read into the data register. - */ -int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data) -{ - u16 val; - int attempts = EEPROM_MAX_POLL; - unsigned int base = adapter->params.pci.vpd_cap_addr; - - if ((addr >= EEPROMSIZE && addr != EEPROM_STAT_ADDR) || (addr & 3)) - return -EINVAL; - - pci_write_config_word(adapter->pdev, base + PCI_VPD_ADDR, addr); - do { - udelay(10); - pci_read_config_word(adapter->pdev, base + PCI_VPD_ADDR, &val); - } while (!(val & PCI_VPD_ADDR_F) && --attempts); - - if (!(val & PCI_VPD_ADDR_F)) { - CH_ERR(adapter, "reading EEPROM address 0x%x failed\n", addr); - return -EIO; - } - pci_read_config_dword(adapter->pdev, base + PCI_VPD_DATA, data); - *data = le32_to_cpu(*data); - return 0; -} - -/** - * t3_seeprom_write - write a VPD EEPROM location - * @adapter: adapter to write - * @addr: EEPROM address - * @data: value to write - * - * Write a 32-bit word to a location in VPD EEPROM using the card's PCI - * VPD ROM capability. - */ -int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data) -{ - u16 val; - int attempts = EEPROM_MAX_POLL; - unsigned int base = adapter->params.pci.vpd_cap_addr; - - if ((addr >= EEPROMSIZE && addr != EEPROM_STAT_ADDR) || (addr & 3)) - return -EINVAL; - - pci_write_config_dword(adapter->pdev, base + PCI_VPD_DATA, - cpu_to_le32(data)); - pci_write_config_word(adapter->pdev,base + PCI_VPD_ADDR, - addr | PCI_VPD_ADDR_F); - do { - msleep(1); - pci_read_config_word(adapter->pdev, base + PCI_VPD_ADDR, &val); - } while ((val & PCI_VPD_ADDR_F) && --attempts); - - if (val & PCI_VPD_ADDR_F) { - CH_ERR(adapter, "write to EEPROM address 0x%x failed\n", addr); - return -EIO; - } - return 0; -} - -/** - * t3_seeprom_wp - enable/disable EEPROM write protection - * @adapter: the adapter - * @enable: 1 to enable write protection, 0 to disable it - * - * Enables or disables write protection on the serial EEPROM. - */ -int t3_seeprom_wp(struct adapter *adapter, int enable) -{ - return t3_seeprom_write(adapter, EEPROM_STAT_ADDR, enable ? 0xc : 0); -} - -/* - * Convert a character holding a hex digit to a number. - */ -static unsigned int hex2int(unsigned char c) -{ - return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10; -} - -/** - * get_vpd_params - read VPD parameters from VPD EEPROM - * @adapter: adapter to read - * @p: where to store the parameters - * - * Reads card parameters stored in VPD EEPROM. - */ -static int get_vpd_params(struct adapter *adapter, struct vpd_params *p) -{ - int i, addr, ret; - struct t3_vpd vpd; - - /* - * Card information is normally at VPD_BASE but some early cards had - * it at 0. - */ - ret = t3_seeprom_read(adapter, VPD_BASE, (u32 *)&vpd); - if (ret) - return ret; - addr = vpd.id_tag == 0x82 ? VPD_BASE : 0; - - for (i = 0; i < sizeof(vpd); i += 4) { - ret = t3_seeprom_read(adapter, addr + i, - (u32 *)((u8 *)&vpd + i)); - if (ret) - return ret; - } - - p->cclk = simple_strtoul(vpd.cclk_data, NULL, 10); - p->mclk = simple_strtoul(vpd.mclk_data, NULL, 10); - p->uclk = simple_strtoul(vpd.uclk_data, NULL, 10); - p->mdc = simple_strtoul(vpd.mdc_data, NULL, 10); - p->mem_timing = simple_strtoul(vpd.mt_data, NULL, 10); - - /* Old eeproms didn't have port information */ - if (adapter->params.rev == 0 && !vpd.port0_data[0]) { - p->port_type[0] = uses_xaui(adapter) ? 1 : 2; - p->port_type[1] = uses_xaui(adapter) ? 6 : 2; - } else { - p->port_type[0] = hex2int(vpd.port0_data[0]); - p->port_type[1] = hex2int(vpd.port1_data[0]); - p->xauicfg[0] = simple_strtoul(vpd.xaui0cfg_data, NULL, 16); - p->xauicfg[1] = simple_strtoul(vpd.xaui1cfg_data, NULL, 16); - } - - for (i = 0; i < 6; i++) - p->eth_base[i] = hex2int(vpd.na_data[2 * i]) * 16 + - hex2int(vpd.na_data[2 * i + 1]); - return 0; -} - -/* serial flash and firmware constants */ -enum { - SF_ATTEMPTS = 5, /* max retries for SF1 operations */ - SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */ - SF_SIZE = SF_SEC_SIZE * 8, /* serial flash size */ - - /* flash command opcodes */ - SF_PROG_PAGE = 2, /* program page */ - SF_WR_DISABLE = 4, /* disable writes */ - SF_RD_STATUS = 5, /* read status register */ - SF_WR_ENABLE = 6, /* enable writes */ - SF_RD_DATA_FAST = 0xb, /* read flash */ - SF_ERASE_SECTOR = 0xd8, /* erase sector */ - - FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */ - FW_VERS_ADDR = 0x77ffc /* flash address holding FW version */ -}; - -/** - * sf1_read - read data from the serial flash - * @adapter: the adapter - * @byte_cnt: number of bytes to read - * @cont: whether another operation will be chained - * @valp: where to store the read data - * - * Reads up to 4 bytes of data from the serial flash. The location of - * the read needs to be specified prior to calling this by issuing the - * appropriate commands to the serial flash. - */ -static int sf1_read(struct adapter *adapter, unsigned int byte_cnt, int cont, - u32 *valp) -{ - int ret; - - if (!byte_cnt || byte_cnt > 4) - return -EINVAL; - if (t3_read_reg(adapter, A_SF_OP) & F_BUSY) - return -EBUSY; - t3_write_reg(adapter, A_SF_OP, V_CONT(cont) | V_BYTECNT(byte_cnt - 1)); - ret = t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10); - if (!ret) - *valp = t3_read_reg(adapter, A_SF_DATA); - return ret; -} - -/** - * sf1_write - write data to the serial flash - * @adapter: the adapter - * @byte_cnt: number of bytes to write - * @cont: whether another operation will be chained - * @val: value to write - * - * Writes up to 4 bytes of data to the serial flash. The location of - * the write needs to be specified prior to calling this by issuing the - * appropriate commands to the serial flash. - */ -static int sf1_write(struct adapter *adapter, unsigned int byte_cnt, int cont, - u32 val) -{ - if (!byte_cnt || byte_cnt > 4) - return -EINVAL; - if (t3_read_reg(adapter, A_SF_OP) & F_BUSY) - return -EBUSY; - t3_write_reg(adapter, A_SF_DATA, val); - t3_write_reg(adapter, A_SF_OP, - V_CONT(cont) | V_BYTECNT(byte_cnt - 1) | V_OP(1)); - return t3_wait_op_done(adapter, A_SF_OP, F_BUSY, 0, SF_ATTEMPTS, 10); -} - -/** - * flash_wait_op - wait for a flash operation to complete - * @adapter: the adapter - * @attempts: max number of polls of the status register - * @delay: delay between polls in ms - * - * Wait for a flash operation to complete by polling the status register. - */ -static int flash_wait_op(struct adapter *adapter, int attempts, int delay) -{ - int ret; - u32 status; - - while (1) { - if ((ret = sf1_write(adapter, 1, 1, SF_RD_STATUS)) != 0 || - (ret = sf1_read(adapter, 1, 0, &status)) != 0) - return ret; - if (!(status & 1)) - return 0; - if (--attempts == 0) - return -EAGAIN; - if (delay) - msleep(delay); - } -} - -/** - * t3_read_flash - read words from serial flash - * @adapter: the adapter - * @addr: the start address for the read - * @nwords: how many 32-bit words to read - * @data: where to store the read data - * @byte_oriented: whether to store data as bytes or as words - * - * Read the specified number of 32-bit words from the serial flash. - * If @byte_oriented is set the read data is stored as a byte array - * (i.e., big-endian), otherwise as 32-bit words in the platform's - * natural endianess. - */ -int t3_read_flash(struct adapter *adapter, unsigned int addr, - unsigned int nwords, u32 *data, int byte_oriented) -{ - int ret; - - if (addr + nwords * sizeof(u32) > SF_SIZE || (addr & 3)) - return -EINVAL; - - addr = swab32(addr) | SF_RD_DATA_FAST; - - if ((ret = sf1_write(adapter, 4, 1, addr)) != 0 || - (ret = sf1_read(adapter, 1, 1, data)) != 0) - return ret; - - for (; nwords; nwords--, data++) { - ret = sf1_read(adapter, 4, nwords > 1, data); - if (ret) - return ret; - if (byte_oriented) - *data = htonl(*data); - } - return 0; -} - -/** - * t3_write_flash - write up to a page of data to the serial flash - * @adapter: the adapter - * @addr: the start address to write - * @n: length of data to write - * @data: the data to write - * - * Writes up to a page of data (256 bytes) to the serial flash starting - * at the given address. - */ -static int t3_write_flash(struct adapter *adapter, unsigned int addr, - unsigned int n, const u8 *data) -{ - int ret; - u32 buf[64]; - unsigned int i, c, left, val, offset = addr & 0xff; - - if (addr + n > SF_SIZE || offset + n > 256) - return -EINVAL; - - val = swab32(addr) | SF_PROG_PAGE; - - if ((ret = sf1_write(adapter, 1, 0, SF_WR_ENABLE)) != 0 || - (ret = sf1_write(adapter, 4, 1, val)) != 0) - return ret; - - for (left = n; left; left -= c) { - c = min(left, 4U); - for (val = 0, i = 0; i < c; ++i) - val = (val << 8) + *data++; - - ret = sf1_write(adapter, c, c != left, val); - if (ret) - return ret; - } - if ((ret = flash_wait_op(adapter, 5, 1)) != 0) - return ret; - - /* Read the page to verify the write succeeded */ - ret = t3_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf, 1); - if (ret) - return ret; - - if (memcmp(data - n, (u8 *) buf + offset, n)) - return -EIO; - return 0; -} - -enum fw_version_type { - FW_VERSION_N3, - FW_VERSION_T3 -}; - -/** - * t3_get_fw_version - read the firmware version - * @adapter: the adapter - * @vers: where to place the version - * - * Reads the FW version from flash. - */ -int t3_get_fw_version(struct adapter *adapter, u32 *vers) -{ - return t3_read_flash(adapter, FW_VERS_ADDR, 1, vers, 0); -} - -/** - * t3_check_fw_version - check if the FW is compatible with this driver - * @adapter: the adapter - * - * Checks if an adapter's FW is compatible with the driver. Returns 0 - * if the versions are compatible, a negative error otherwise. - */ -int t3_check_fw_version(struct adapter *adapter) -{ - int ret; - u32 vers; - unsigned int type, major, minor; - - ret = t3_get_fw_version(adapter, &vers); - if (ret) - return ret; - - type = G_FW_VERSION_TYPE(vers); - major = G_FW_VERSION_MAJOR(vers); - minor = G_FW_VERSION_MINOR(vers); - - if (type == FW_VERSION_T3 && major == 3 && minor == 1) - return 0; - - CH_ERR(adapter, "found wrong FW version(%u.%u), " - "driver needs version 3.1\n", major, minor); - return -EINVAL; -} - -/** - * t3_flash_erase_sectors - erase a range of flash sectors - * @adapter: the adapter - * @start: the first sector to erase - * @end: the last sector to erase - * - * Erases the sectors in the given range. - */ -static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end) -{ - while (start <= end) { - int ret; - - if ((ret = sf1_write(adapter, 1, 0, SF_WR_ENABLE)) != 0 || - (ret = sf1_write(adapter, 4, 0, - SF_ERASE_SECTOR | (start << 8))) != 0 || - (ret = flash_wait_op(adapter, 5, 500)) != 0) - return ret; - start++; - } - return 0; -} - -/* - * t3_load_fw - download firmware - * @adapter: the adapter - * @fw_data: the firrware image to write - * @size: image size - * - * Write the supplied firmware image to the card's serial flash. - * The FW image has the following sections: @size - 8 bytes of code and - * data, followed by 4 bytes of FW version, followed by the 32-bit - * 1's complement checksum of the whole image. - */ -int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size) -{ - u32 csum; - unsigned int i; - const u32 *p = (const u32 *)fw_data; - int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16; - - if (size & 3) - return -EINVAL; - if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR) - return -EFBIG; - - for (csum = 0, i = 0; i < size / sizeof(csum); i++) - csum += ntohl(p[i]); - if (csum != 0xffffffff) { - CH_ERR(adapter, "corrupted firmware image, checksum %u\n", - csum); - return -EINVAL; - } - - ret = t3_flash_erase_sectors(adapter, fw_sector, fw_sector); - if (ret) - goto out; - - size -= 8; /* trim off version and checksum */ - for (addr = FW_FLASH_BOOT_ADDR; size;) { - unsigned int chunk_size = min(size, 256U); - - ret = t3_write_flash(adapter, addr, chunk_size, fw_data); - if (ret) - goto out; - - addr += chunk_size; - fw_data += chunk_size; - size -= chunk_size; - } - - ret = t3_write_flash(adapter, FW_VERS_ADDR, 4, fw_data); -out: - if (ret) - CH_ERR(adapter, "firmware download failed, error %d\n", ret); - return ret; -} - -#define CIM_CTL_BASE 0x2000 - -/** - * t3_cim_ctl_blk_read - read a block from CIM control region - * - * @adap: the adapter - * @addr: the start address within the CIM control region - * @n: number of words to read - * @valp: where to store the result - * - * Reads a block of 4-byte words from the CIM control region. - */ -int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr, - unsigned int n, unsigned int *valp) -{ - int ret = 0; - - if (t3_read_reg(adap, A_CIM_HOST_ACC_CTRL) & F_HOSTBUSY) - return -EBUSY; - - for ( ; !ret && n--; addr += 4) { - t3_write_reg(adap, A_CIM_HOST_ACC_CTRL, CIM_CTL_BASE + addr); - ret = t3_wait_op_done(adap, A_CIM_HOST_ACC_CTRL, F_HOSTBUSY, - 0, 5, 2); - if (!ret) - *valp++ = t3_read_reg(adap, A_CIM_HOST_ACC_DATA); - } - return ret; -} - - -/** - * t3_link_changed - handle interface link changes - * @adapter: the adapter - * @port_id: the port index that changed link state - * - * Called when a port's link settings change to propagate the new values - * to the associated PHY and MAC. After performing the common tasks it - * invokes an OS-specific handler. - */ -void t3_link_changed(struct adapter *adapter, int port_id) -{ - int link_ok, speed, duplex, fc; - struct port_info *pi = adap2pinfo(adapter, port_id); - struct cphy *phy = &pi->phy; - struct cmac *mac = &pi->mac; - struct link_config *lc = &pi->link_config; - - phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); - - if (link_ok != lc->link_ok && adapter->params.rev > 0 && - uses_xaui(adapter)) { - if (link_ok) - t3b_pcs_reset(mac); - t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, - link_ok ? F_TXACTENABLE | F_RXEN : 0); - } - lc->link_ok = link_ok; - lc->speed = speed < 0 ? SPEED_INVALID : speed; - lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex; - if (lc->requested_fc & PAUSE_AUTONEG) - fc &= lc->requested_fc; - else - fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); - - if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) { - /* Set MAC speed, duplex, and flow control to match PHY. */ - t3_mac_set_speed_duplex_fc(mac, speed, duplex, fc); - lc->fc = fc; - } - - t3_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc); -} - -/** - * t3_link_start - apply link configuration to MAC/PHY - * @phy: the PHY to setup - * @mac: the MAC to setup - * @lc: the requested link configuration - * - * Set up a port's MAC and PHY according to a desired link configuration. - * - If the PHY can auto-negotiate first decide what to advertise, then - * enable/disable auto-negotiation as desired, and reset. - * - If the PHY does not auto-negotiate just reset it. - * - If auto-negotiation is off set the MAC to the proper speed/duplex/FC, - * otherwise do it later based on the outcome of auto-negotiation. - */ -int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) -{ - unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); - - lc->link_ok = 0; - if (lc->supported & SUPPORTED_Autoneg) { - lc->advertising &= ~(ADVERTISED_Asym_Pause | ADVERTISED_Pause); - if (fc) { - lc->advertising |= ADVERTISED_Asym_Pause; - if (fc & PAUSE_RX) - lc->advertising |= ADVERTISED_Pause; - } - phy->ops->advertise(phy, lc->advertising); - - if (lc->autoneg == AUTONEG_DISABLE) { - lc->speed = lc->requested_speed; - lc->duplex = lc->requested_duplex; - lc->fc = (unsigned char)fc; - t3_mac_set_speed_duplex_fc(mac, lc->speed, lc->duplex, - fc); - /* Also disables autoneg */ - phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); - phy->ops->reset(phy, 0); - } else - phy->ops->autoneg_enable(phy); - } else { - t3_mac_set_speed_duplex_fc(mac, -1, -1, fc); - lc->fc = (unsigned char)fc; - phy->ops->reset(phy, 0); - } - return 0; -} - -/** - * t3_set_vlan_accel - control HW VLAN extraction - * @adapter: the adapter - * @ports: bitmap of adapter ports to operate on - * @on: enable (1) or disable (0) HW VLAN extraction - * - * Enables or disables HW extraction of VLAN tags for the given port. - */ -void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on) -{ - t3_set_reg_field(adapter, A_TP_OUT_CONFIG, - ports << S_VLANEXTRACTIONENABLE, - on ? (ports << S_VLANEXTRACTIONENABLE) : 0); -} - -struct intr_info { - unsigned int mask; /* bits to check in interrupt status */ - const char *msg; /* message to print or NULL */ - short stat_idx; /* stat counter to increment or -1 */ - unsigned short fatal:1; /* whether the condition reported is fatal */ -}; - -/** - * t3_handle_intr_status - table driven interrupt handler - * @adapter: the adapter that generated the interrupt - * @reg: the interrupt status register to process - * @mask: a mask to apply to the interrupt status - * @acts: table of interrupt actions - * @stats: statistics counters tracking interrupt occurences - * - * A table driven interrupt handler that applies a set of masks to an - * interrupt status word and performs the corresponding actions if the - * interrupts described by the mask have occured. The actions include - * optionally printing a warning or alert message, and optionally - * incrementing a stat counter. The table is terminated by an entry - * specifying mask 0. Returns the number of fatal interrupt conditions. - */ -static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg, - unsigned int mask, - const struct intr_info *acts, - unsigned long *stats) -{ - int fatal = 0; - unsigned int status = t3_read_reg(adapter, reg) & mask; - - for (; acts->mask; ++acts) { - if (!(status & acts->mask)) - continue; - if (acts->fatal) { - fatal++; - CH_ALERT(adapter, "%s (0x%x)\n", - acts->msg, status & acts->mask); - } else if (acts->msg) - CH_WARN(adapter, "%s (0x%x)\n", - acts->msg, status & acts->mask); - if (acts->stat_idx >= 0) - stats[acts->stat_idx]++; - } - if (status) /* clear processed interrupts */ - t3_write_reg(adapter, reg, status); - return fatal; -} - -#define SGE_INTR_MASK (F_RSPQDISABLED) -#define MC5_INTR_MASK (F_PARITYERR | F_ACTRGNFULL | F_UNKNOWNCMD | \ - F_REQQPARERR | F_DISPQPARERR | F_DELACTEMPTY | \ - F_NFASRCHFAIL) -#define MC7_INTR_MASK (F_AE | F_UE | F_CE | V_PE(M_PE)) -#define XGM_INTR_MASK (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \ - V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR) | \ - F_TXFIFO_UNDERRUN | F_RXFIFO_OVERFLOW) -#define PCIX_INTR_MASK (F_MSTDETPARERR | F_SIGTARABT | F_RCVTARABT | \ - F_RCVMSTABT | F_SIGSYSERR | F_DETPARERR | \ - F_SPLCMPDIS | F_UNXSPLCMP | F_RCVSPLCMPERR | \ - F_DETCORECCERR | F_DETUNCECCERR | F_PIOPARERR | \ - V_WFPARERR(M_WFPARERR) | V_RFPARERR(M_RFPARERR) | \ - V_CFPARERR(M_CFPARERR) /* | V_MSIXPARERR(M_MSIXPARERR) */) -#define PCIE_INTR_MASK (F_UNXSPLCPLERRR | F_UNXSPLCPLERRC | F_PCIE_PIOPARERR |\ - F_PCIE_WFPARERR | F_PCIE_RFPARERR | F_PCIE_CFPARERR | \ - /* V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR) | */ \ - V_BISTERR(M_BISTERR) | F_PEXERR) -#define ULPRX_INTR_MASK F_PARERR -#define ULPTX_INTR_MASK 0 -#define CPLSW_INTR_MASK (F_TP_FRAMING_ERROR | \ - F_SGE_FRAMING_ERROR | F_CIM_FRAMING_ERROR | \ - F_ZERO_SWITCH_ERROR) -#define CIM_INTR_MASK (F_BLKWRPLINT | F_BLKRDPLINT | F_BLKWRCTLINT | \ - F_BLKRDCTLINT | F_BLKWRFLASHINT | F_BLKRDFLASHINT | \ - F_SGLWRFLASHINT | F_WRBLKFLASHINT | F_BLKWRBOOTINT | \ - F_FLASHRANGEINT | F_SDRAMRANGEINT | F_RSVDSPACEINT) -#define PMTX_INTR_MASK (F_ZERO_C_CMD_ERROR | ICSPI_FRM_ERR | OESPI_FRM_ERR | \ - V_ICSPI_PAR_ERROR(M_ICSPI_PAR_ERROR) | \ - V_OESPI_PAR_ERROR(M_OESPI_PAR_ERROR)) -#define PMRX_INTR_MASK (F_ZERO_E_CMD_ERROR | IESPI_FRM_ERR | OCSPI_FRM_ERR | \ - V_IESPI_PAR_ERROR(M_IESPI_PAR_ERROR) | \ - V_OCSPI_PAR_ERROR(M_OCSPI_PAR_ERROR)) -#define MPS_INTR_MASK (V_TX0TPPARERRENB(M_TX0TPPARERRENB) | \ - V_TX1TPPARERRENB(M_TX1TPPARERRENB) | \ - V_RXTPPARERRENB(M_RXTPPARERRENB) | \ - V_MCAPARERRENB(M_MCAPARERRENB)) -#define PL_INTR_MASK (F_T3DBG | F_XGMAC0_0 | F_XGMAC0_1 | F_MC5A | F_PM1_TX | \ - F_PM1_RX | F_ULP2_TX | F_ULP2_RX | F_TP1 | F_CIM | \ - F_MC7_CM | F_MC7_PMTX | F_MC7_PMRX | F_SGE3 | F_PCIM0 | \ - F_MPS0 | F_CPL_SWITCH) - -/* - * Interrupt handler for the PCIX1 module. - */ -static void pci_intr_handler(struct adapter *adapter) -{ - static const struct intr_info pcix1_intr_info[] = { - {F_MSTDETPARERR, "PCI master detected parity error", -1, 1}, - {F_SIGTARABT, "PCI signaled target abort", -1, 1}, - {F_RCVTARABT, "PCI received target abort", -1, 1}, - {F_RCVMSTABT, "PCI received master abort", -1, 1}, - {F_SIGSYSERR, "PCI signaled system error", -1, 1}, - {F_DETPARERR, "PCI detected parity error", -1, 1}, - {F_SPLCMPDIS, "PCI split completion discarded", -1, 1}, - {F_UNXSPLCMP, "PCI unexpected split completion error", -1, 1}, - {F_RCVSPLCMPERR, "PCI received split completion error", -1, - 1}, - {F_DETCORECCERR, "PCI correctable ECC error", - STAT_PCI_CORR_ECC, 0}, - {F_DETUNCECCERR, "PCI uncorrectable ECC error", -1, 1}, - {F_PIOPARERR, "PCI PIO FIFO parity error", -1, 1}, - {V_WFPARERR(M_WFPARERR), "PCI write FIFO parity error", -1, - 1}, - {V_RFPARERR(M_RFPARERR), "PCI read FIFO parity error", -1, - 1}, - {V_CFPARERR(M_CFPARERR), "PCI command FIFO parity error", -1, - 1}, - {V_MSIXPARERR(M_MSIXPARERR), "PCI MSI-X table/PBA parity " - "error", -1, 1}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_PCIX_INT_CAUSE, PCIX_INTR_MASK, - pcix1_intr_info, adapter->irq_stats)) - t3_fatal_err(adapter); -} - -/* - * Interrupt handler for the PCIE module. - */ -static void pcie_intr_handler(struct adapter *adapter) -{ - static const struct intr_info pcie_intr_info[] = { - {F_PEXERR, "PCI PEX error", -1, 1}, - {F_UNXSPLCPLERRR, - "PCI unexpected split completion DMA read error", -1, 1}, - {F_UNXSPLCPLERRC, - "PCI unexpected split completion DMA command error", -1, 1}, - {F_PCIE_PIOPARERR, "PCI PIO FIFO parity error", -1, 1}, - {F_PCIE_WFPARERR, "PCI write FIFO parity error", -1, 1}, - {F_PCIE_RFPARERR, "PCI read FIFO parity error", -1, 1}, - {F_PCIE_CFPARERR, "PCI command FIFO parity error", -1, 1}, - {V_PCIE_MSIXPARERR(M_PCIE_MSIXPARERR), - "PCI MSI-X table/PBA parity error", -1, 1}, - {V_BISTERR(M_BISTERR), "PCI BIST error", -1, 1}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_PCIE_INT_CAUSE, PCIE_INTR_MASK, - pcie_intr_info, adapter->irq_stats)) - t3_fatal_err(adapter); -} - -/* - * TP interrupt handler. - */ -static void tp_intr_handler(struct adapter *adapter) -{ - static const struct intr_info tp_intr_info[] = { - {0xffffff, "TP parity error", -1, 1}, - {0x1000000, "TP out of Rx pages", -1, 1}, - {0x2000000, "TP out of Tx pages", -1, 1}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_TP_INT_CAUSE, 0xffffffff, - tp_intr_info, NULL)) - t3_fatal_err(adapter); -} - -/* - * CIM interrupt handler. - */ -static void cim_intr_handler(struct adapter *adapter) -{ - static const struct intr_info cim_intr_info[] = { - {F_RSVDSPACEINT, "CIM reserved space write", -1, 1}, - {F_SDRAMRANGEINT, "CIM SDRAM address out of range", -1, 1}, - {F_FLASHRANGEINT, "CIM flash address out of range", -1, 1}, - {F_BLKWRBOOTINT, "CIM block write to boot space", -1, 1}, - {F_WRBLKFLASHINT, "CIM write to cached flash space", -1, 1}, - {F_SGLWRFLASHINT, "CIM single write to flash space", -1, 1}, - {F_BLKRDFLASHINT, "CIM block read from flash space", -1, 1}, - {F_BLKWRFLASHINT, "CIM block write to flash space", -1, 1}, - {F_BLKRDCTLINT, "CIM block read from CTL space", -1, 1}, - {F_BLKWRCTLINT, "CIM block write to CTL space", -1, 1}, - {F_BLKRDPLINT, "CIM block read from PL space", -1, 1}, - {F_BLKWRPLINT, "CIM block write to PL space", -1, 1}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_CIM_HOST_INT_CAUSE, 0xffffffff, - cim_intr_info, NULL)) - t3_fatal_err(adapter); -} - -/* - * ULP RX interrupt handler. - */ -static void ulprx_intr_handler(struct adapter *adapter) -{ - static const struct intr_info ulprx_intr_info[] = { - {F_PARERR, "ULP RX parity error", -1, 1}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_ULPRX_INT_CAUSE, 0xffffffff, - ulprx_intr_info, NULL)) - t3_fatal_err(adapter); -} - -/* - * ULP TX interrupt handler. - */ -static void ulptx_intr_handler(struct adapter *adapter) -{ - static const struct intr_info ulptx_intr_info[] = { - {F_PBL_BOUND_ERR_CH0, "ULP TX channel 0 PBL out of bounds", - STAT_ULP_CH0_PBL_OOB, 0}, - {F_PBL_BOUND_ERR_CH1, "ULP TX channel 1 PBL out of bounds", - STAT_ULP_CH1_PBL_OOB, 0}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_ULPTX_INT_CAUSE, 0xffffffff, - ulptx_intr_info, adapter->irq_stats)) - t3_fatal_err(adapter); -} - -#define ICSPI_FRM_ERR (F_ICSPI0_FIFO2X_RX_FRAMING_ERROR | \ - F_ICSPI1_FIFO2X_RX_FRAMING_ERROR | F_ICSPI0_RX_FRAMING_ERROR | \ - F_ICSPI1_RX_FRAMING_ERROR | F_ICSPI0_TX_FRAMING_ERROR | \ - F_ICSPI1_TX_FRAMING_ERROR) -#define OESPI_FRM_ERR (F_OESPI0_RX_FRAMING_ERROR | \ - F_OESPI1_RX_FRAMING_ERROR | F_OESPI0_TX_FRAMING_ERROR | \ - F_OESPI1_TX_FRAMING_ERROR | F_OESPI0_OFIFO2X_TX_FRAMING_ERROR | \ - F_OESPI1_OFIFO2X_TX_FRAMING_ERROR) - -/* - * PM TX interrupt handler. - */ -static void pmtx_intr_handler(struct adapter *adapter) -{ - static const struct intr_info pmtx_intr_info[] = { - {F_ZERO_C_CMD_ERROR, "PMTX 0-length pcmd", -1, 1}, - {ICSPI_FRM_ERR, "PMTX ispi framing error", -1, 1}, - {OESPI_FRM_ERR, "PMTX ospi framing error", -1, 1}, - {V_ICSPI_PAR_ERROR(M_ICSPI_PAR_ERROR), - "PMTX ispi parity error", -1, 1}, - {V_OESPI_PAR_ERROR(M_OESPI_PAR_ERROR), - "PMTX ospi parity error", -1, 1}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_PM1_TX_INT_CAUSE, 0xffffffff, - pmtx_intr_info, NULL)) - t3_fatal_err(adapter); -} - -#define IESPI_FRM_ERR (F_IESPI0_FIFO2X_RX_FRAMING_ERROR | \ - F_IESPI1_FIFO2X_RX_FRAMING_ERROR | F_IESPI0_RX_FRAMING_ERROR | \ - F_IESPI1_RX_FRAMING_ERROR | F_IESPI0_TX_FRAMING_ERROR | \ - F_IESPI1_TX_FRAMING_ERROR) -#define OCSPI_FRM_ERR (F_OCSPI0_RX_FRAMING_ERROR | \ - F_OCSPI1_RX_FRAMING_ERROR | F_OCSPI0_TX_FRAMING_ERROR | \ - F_OCSPI1_TX_FRAMING_ERROR | F_OCSPI0_OFIFO2X_TX_FRAMING_ERROR | \ - F_OCSPI1_OFIFO2X_TX_FRAMING_ERROR) - -/* - * PM RX interrupt handler. - */ -static void pmrx_intr_handler(struct adapter *adapter) -{ - static const struct intr_info pmrx_intr_info[] = { - {F_ZERO_E_CMD_ERROR, "PMRX 0-length pcmd", -1, 1}, - {IESPI_FRM_ERR, "PMRX ispi framing error", -1, 1}, - {OCSPI_FRM_ERR, "PMRX ospi framing error", -1, 1}, - {V_IESPI_PAR_ERROR(M_IESPI_PAR_ERROR), - "PMRX ispi parity error", -1, 1}, - {V_OCSPI_PAR_ERROR(M_OCSPI_PAR_ERROR), - "PMRX ospi parity error", -1, 1}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_PM1_RX_INT_CAUSE, 0xffffffff, - pmrx_intr_info, NULL)) - t3_fatal_err(adapter); -} - -/* - * CPL switch interrupt handler. - */ -static void cplsw_intr_handler(struct adapter *adapter) -{ - static const struct intr_info cplsw_intr_info[] = { -/* { F_CIM_OVFL_ERROR, "CPL switch CIM overflow", -1, 1 }, */ - {F_TP_FRAMING_ERROR, "CPL switch TP framing error", -1, 1}, - {F_SGE_FRAMING_ERROR, "CPL switch SGE framing error", -1, 1}, - {F_CIM_FRAMING_ERROR, "CPL switch CIM framing error", -1, 1}, - {F_ZERO_SWITCH_ERROR, "CPL switch no-switch error", -1, 1}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_CPL_INTR_CAUSE, 0xffffffff, - cplsw_intr_info, NULL)) - t3_fatal_err(adapter); -} - -/* - * MPS interrupt handler. - */ -static void mps_intr_handler(struct adapter *adapter) -{ - static const struct intr_info mps_intr_info[] = { - {0x1ff, "MPS parity error", -1, 1}, - {0} - }; - - if (t3_handle_intr_status(adapter, A_MPS_INT_CAUSE, 0xffffffff, - mps_intr_info, NULL)) - t3_fatal_err(adapter); -} - -#define MC7_INTR_FATAL (F_UE | V_PE(M_PE) | F_AE) - -/* - * MC7 interrupt handler. - */ -static void mc7_intr_handler(struct mc7 *mc7) -{ - struct adapter *adapter = mc7->adapter; - u32 cause = t3_read_reg(adapter, mc7->offset + A_MC7_INT_CAUSE); - - if (cause & F_CE) { - mc7->stats.corr_err++; - CH_WARN(adapter, "%s MC7 correctable error at addr 0x%x, " - "data 0x%x 0x%x 0x%x\n", mc7->name, - t3_read_reg(adapter, mc7->offset + A_MC7_CE_ADDR), - t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA0), - t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA1), - t3_read_reg(adapter, mc7->offset + A_MC7_CE_DATA2)); - } - - if (cause & F_UE) { - mc7->stats.uncorr_err++; - CH_ALERT(adapter, "%s MC7 uncorrectable error at addr 0x%x, " - "data 0x%x 0x%x 0x%x\n", mc7->name, - t3_read_reg(adapter, mc7->offset + A_MC7_UE_ADDR), - t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA0), - t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA1), - t3_read_reg(adapter, mc7->offset + A_MC7_UE_DATA2)); - } - - if (G_PE(cause)) { - mc7->stats.parity_err++; - CH_ALERT(adapter, "%s MC7 parity error 0x%x\n", - mc7->name, G_PE(cause)); - } - - if (cause & F_AE) { - u32 addr = 0; - - if (adapter->params.rev > 0) - addr = t3_read_reg(adapter, - mc7->offset + A_MC7_ERR_ADDR); - mc7->stats.addr_err++; - CH_ALERT(adapter, "%s MC7 address error: 0x%x\n", - mc7->name, addr); - } - - if (cause & MC7_INTR_FATAL) - t3_fatal_err(adapter); - - t3_write_reg(adapter, mc7->offset + A_MC7_INT_CAUSE, cause); -} - -#define XGM_INTR_FATAL (V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR) | \ - V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR)) -/* - * XGMAC interrupt handler. - */ -static int mac_intr_handler(struct adapter *adap, unsigned int idx) -{ - struct cmac *mac = &adap2pinfo(adap, idx)->mac; - u32 cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset); - - if (cause & V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR)) { - mac->stats.tx_fifo_parity_err++; - CH_ALERT(adap, "port%d: MAC TX FIFO parity error\n", idx); - } - if (cause & V_RXFIFO_PRTY_ERR(M_RXFIFO_PRTY_ERR)) { - mac->stats.rx_fifo_parity_err++; - CH_ALERT(adap, "port%d: MAC RX FIFO parity error\n", idx); - } - if (cause & F_TXFIFO_UNDERRUN) - mac->stats.tx_fifo_urun++; - if (cause & F_RXFIFO_OVERFLOW) - mac->stats.rx_fifo_ovfl++; - if (cause & V_SERDES_LOS(M_SERDES_LOS)) - mac->stats.serdes_signal_loss++; - if (cause & F_XAUIPCSCTCERR) - mac->stats.xaui_pcs_ctc_err++; - if (cause & F_XAUIPCSALIGNCHANGE) - mac->stats.xaui_pcs_align_change++; - - t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause); - if (cause & XGM_INTR_FATAL) - t3_fatal_err(adap); - return cause != 0; -} - -/* - * Interrupt handler for PHY events. - */ -int t3_phy_intr_handler(struct adapter *adapter) -{ - static const int intr_gpio_bits[] = { 8, 0x20 }; - - u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE); - - for_each_port(adapter, i) { - if (cause & intr_gpio_bits[i]) { - struct cphy *phy = &adap2pinfo(adapter, i)->phy; - int phy_cause = phy->ops->intr_handler(phy); - - if (phy_cause & cphy_cause_link_change) - t3_link_changed(adapter, i); - if (phy_cause & cphy_cause_fifo_error) - phy->fifo_errors++; - } - } - - t3_write_reg(adapter, A_T3DBG_INT_CAUSE, cause); - return 0; -} - -/* - * T3 slow path (non-data) interrupt handler. - */ -int t3_slow_intr_handler(struct adapter *adapter) -{ - u32 cause = t3_read_reg(adapter, A_PL_INT_CAUSE0); - - cause &= adapter->slow_intr_mask; - if (!cause) - return 0; - if (cause & F_PCIM0) { - if (is_pcie(adapter)) - pcie_intr_handler(adapter); - else - pci_intr_handler(adapter); - } - if (cause & F_SGE3) - t3_sge_err_intr_handler(adapter); - if (cause & F_MC7_PMRX) - mc7_intr_handler(&adapter->pmrx); - if (cause & F_MC7_PMTX) - mc7_intr_handler(&adapter->pmtx); - if (cause & F_MC7_CM) - mc7_intr_handler(&adapter->cm); - if (cause & F_CIM) - cim_intr_handler(adapter); - if (cause & F_TP1) - tp_intr_handler(adapter); - if (cause & F_ULP2_RX) - ulprx_intr_handler(adapter); - if (cause & F_ULP2_TX) - ulptx_intr_handler(adapter); - if (cause & F_PM1_RX) - pmrx_intr_handler(adapter); - if (cause & F_PM1_TX) - pmtx_intr_handler(adapter); - if (cause & F_CPL_SWITCH) - cplsw_intr_handler(adapter); - if (cause & F_MPS0) - mps_intr_handler(adapter); - if (cause & F_MC5A) - t3_mc5_intr_handler(&adapter->mc5); - if (cause & F_XGMAC0_0) - mac_intr_handler(adapter, 0); - if (cause & F_XGMAC0_1) - mac_intr_handler(adapter, 1); - if (cause & F_T3DBG) - t3_os_ext_intr_handler(adapter); - - /* Clear the interrupts just processed. */ - t3_write_reg(adapter, A_PL_INT_CAUSE0, cause); - t3_read_reg(adapter, A_PL_INT_CAUSE0); /* flush */ - return 1; -} - -/** - * t3_intr_enable - enable interrupts - * @adapter: the adapter whose interrupts should be enabled - * - * Enable interrupts by setting the interrupt enable registers of the - * various HW modules and then enabling the top-level interrupt - * concentrator. - */ -void t3_intr_enable(struct adapter *adapter) -{ - static const struct addr_val_pair intr_en_avp[] = { - {A_SG_INT_ENABLE, SGE_INTR_MASK}, - {A_MC7_INT_ENABLE, MC7_INTR_MASK}, - {A_MC7_INT_ENABLE - MC7_PMRX_BASE_ADDR + MC7_PMTX_BASE_ADDR, - MC7_INTR_MASK}, - {A_MC7_INT_ENABLE - MC7_PMRX_BASE_ADDR + MC7_CM_BASE_ADDR, - MC7_INTR_MASK}, - {A_MC5_DB_INT_ENABLE, MC5_INTR_MASK}, - {A_ULPRX_INT_ENABLE, ULPRX_INTR_MASK}, - {A_TP_INT_ENABLE, 0x3bfffff}, - {A_PM1_TX_INT_ENABLE, PMTX_INTR_MASK}, - {A_PM1_RX_INT_ENABLE, PMRX_INTR_MASK}, - {A_CIM_HOST_INT_ENABLE, CIM_INTR_MASK}, - {A_MPS_INT_ENABLE, MPS_INTR_MASK}, - }; - - adapter->slow_intr_mask = PL_INTR_MASK; - - t3_write_regs(adapter, intr_en_avp, ARRAY_SIZE(intr_en_avp), 0); - - if (adapter->params.rev > 0) { - t3_write_reg(adapter, A_CPL_INTR_ENABLE, - CPLSW_INTR_MASK | F_CIM_OVFL_ERROR); - t3_write_reg(adapter, A_ULPTX_INT_ENABLE, - ULPTX_INTR_MASK | F_PBL_BOUND_ERR_CH0 | - F_PBL_BOUND_ERR_CH1); - } else { - t3_write_reg(adapter, A_CPL_INTR_ENABLE, CPLSW_INTR_MASK); - t3_write_reg(adapter, A_ULPTX_INT_ENABLE, ULPTX_INTR_MASK); - } - - t3_write_reg(adapter, A_T3DBG_GPIO_ACT_LOW, - adapter_info(adapter)->gpio_intr); - t3_write_reg(adapter, A_T3DBG_INT_ENABLE, - adapter_info(adapter)->gpio_intr); - if (is_pcie(adapter)) - t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK); - else - t3_write_reg(adapter, A_PCIX_INT_ENABLE, PCIX_INTR_MASK); - t3_write_reg(adapter, A_PL_INT_ENABLE0, adapter->slow_intr_mask); - t3_read_reg(adapter, A_PL_INT_ENABLE0); /* flush */ -} - -/** - * t3_intr_disable - disable a card's interrupts - * @adapter: the adapter whose interrupts should be disabled - * - * Disable interrupts. We only disable the top-level interrupt - * concentrator and the SGE data interrupts. - */ -void t3_intr_disable(struct adapter *adapter) -{ - t3_write_reg(adapter, A_PL_INT_ENABLE0, 0); - t3_read_reg(adapter, A_PL_INT_ENABLE0); /* flush */ - adapter->slow_intr_mask = 0; -} - -/** - * t3_intr_clear - clear all interrupts - * @adapter: the adapter whose interrupts should be cleared - * - * Clears all interrupts. - */ -void t3_intr_clear(struct adapter *adapter) -{ - static const unsigned int cause_reg_addr[] = { - A_SG_INT_CAUSE, - A_SG_RSPQ_FL_STATUS, - A_PCIX_INT_CAUSE, - A_MC7_INT_CAUSE, - A_MC7_INT_CAUSE - MC7_PMRX_BASE_ADDR + MC7_PMTX_BASE_ADDR, - A_MC7_INT_CAUSE - MC7_PMRX_BASE_ADDR + MC7_CM_BASE_ADDR, - A_CIM_HOST_INT_CAUSE, - A_TP_INT_CAUSE, - A_MC5_DB_INT_CAUSE, - A_ULPRX_INT_CAUSE, - A_ULPTX_INT_CAUSE, - A_CPL_INTR_CAUSE, - A_PM1_TX_INT_CAUSE, - A_PM1_RX_INT_CAUSE, - A_MPS_INT_CAUSE, - A_T3DBG_INT_CAUSE, - }; - unsigned int i; - - /* Clear PHY and MAC interrupts for each port. */ - for_each_port(adapter, i) - t3_port_intr_clear(adapter, i); - - for (i = 0; i < ARRAY_SIZE(cause_reg_addr); ++i) - t3_write_reg(adapter, cause_reg_addr[i], 0xffffffff); - - t3_write_reg(adapter, A_PL_INT_CAUSE0, 0xffffffff); - t3_read_reg(adapter, A_PL_INT_CAUSE0); /* flush */ -} - -/** - * t3_port_intr_enable - enable port-specific interrupts - * @adapter: associated adapter - * @idx: index of port whose interrupts should be enabled - * - * Enable port-specific (i.e., MAC and PHY) interrupts for the given - * adapter port. - */ -void t3_port_intr_enable(struct adapter *adapter, int idx) -{ - struct cphy *phy = &adap2pinfo(adapter, idx)->phy; - - t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), XGM_INTR_MASK); - t3_read_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx)); /* flush */ - phy->ops->intr_enable(phy); -} - -/** - * t3_port_intr_disable - disable port-specific interrupts - * @adapter: associated adapter - * @idx: index of port whose interrupts should be disabled - * - * Disable port-specific (i.e., MAC and PHY) interrupts for the given - * adapter port. - */ -void t3_port_intr_disable(struct adapter *adapter, int idx) -{ - struct cphy *phy = &adap2pinfo(adapter, idx)->phy; - - t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), 0); - t3_read_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx)); /* flush */ - phy->ops->intr_disable(phy); -} - -/** - * t3_port_intr_clear - clear port-specific interrupts - * @adapter: associated adapter - * @idx: index of port whose interrupts to clear - * - * Clear port-specific (i.e., MAC and PHY) interrupts for the given - * adapter port. - */ -void t3_port_intr_clear(struct adapter *adapter, int idx) -{ - struct cphy *phy = &adap2pinfo(adapter, idx)->phy; - - t3_write_reg(adapter, XGM_REG(A_XGM_INT_CAUSE, idx), 0xffffffff); - t3_read_reg(adapter, XGM_REG(A_XGM_INT_CAUSE, idx)); /* flush */ - phy->ops->intr_clear(phy); -} - -/** - * t3_sge_write_context - write an SGE context - * @adapter: the adapter - * @id: the context id - * @type: the context type - * - * Program an SGE context with the values already loaded in the - * CONTEXT_DATA? registers. - */ -static int t3_sge_write_context(struct adapter *adapter, unsigned int id, - unsigned int type) -{ - t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0xffffffff); - t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0xffffffff); - t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0xffffffff); - t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0xffffffff); - t3_write_reg(adapter, A_SG_CONTEXT_CMD, - V_CONTEXT_CMD_OPCODE(1) | type | V_CONTEXT(id)); - return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); -} - -/** - * t3_sge_init_ecntxt - initialize an SGE egress context - * @adapter: the adapter to configure - * @id: the context id - * @gts_enable: whether to enable GTS for the context - * @type: the egress context type - * @respq: associated response queue - * @base_addr: base address of queue - * @size: number of queue entries - * @token: uP token - * @gen: initial generation value for the context - * @cidx: consumer pointer - * - * Initialize an SGE egress context and make it ready for use. If the - * platform allows concurrent context operations, the caller is - * responsible for appropriate locking. - */ -int t3_sge_init_ecntxt(struct adapter *adapter, unsigned int id, int gts_enable, - enum sge_context_type type, int respq, u64 base_addr, - unsigned int size, unsigned int token, int gen, - unsigned int cidx) -{ - unsigned int credits = type == SGE_CNTXT_OFLD ? 0 : FW_WR_NUM; - - if (base_addr & 0xfff) /* must be 4K aligned */ - return -EINVAL; - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - base_addr >>= 12; - t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_EC_INDEX(cidx) | - V_EC_CREDITS(credits) | V_EC_GTS(gts_enable)); - t3_write_reg(adapter, A_SG_CONTEXT_DATA1, V_EC_SIZE(size) | - V_EC_BASE_LO(base_addr & 0xffff)); - base_addr >>= 16; - t3_write_reg(adapter, A_SG_CONTEXT_DATA2, base_addr); - base_addr >>= 32; - t3_write_reg(adapter, A_SG_CONTEXT_DATA3, - V_EC_BASE_HI(base_addr & 0xf) | V_EC_RESPQ(respq) | - V_EC_TYPE(type) | V_EC_GEN(gen) | V_EC_UP_TOKEN(token) | - F_EC_VALID); - return t3_sge_write_context(adapter, id, F_EGRESS); -} - -/** - * t3_sge_init_flcntxt - initialize an SGE free-buffer list context - * @adapter: the adapter to configure - * @id: the context id - * @gts_enable: whether to enable GTS for the context - * @base_addr: base address of queue - * @size: number of queue entries - * @bsize: size of each buffer for this queue - * @cong_thres: threshold to signal congestion to upstream producers - * @gen: initial generation value for the context - * @cidx: consumer pointer - * - * Initialize an SGE free list context and make it ready for use. The - * caller is responsible for ensuring only one context operation occurs - * at a time. - */ -int t3_sge_init_flcntxt(struct adapter *adapter, unsigned int id, - int gts_enable, u64 base_addr, unsigned int size, - unsigned int bsize, unsigned int cong_thres, int gen, - unsigned int cidx) -{ - if (base_addr & 0xfff) /* must be 4K aligned */ - return -EINVAL; - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - base_addr >>= 12; - t3_write_reg(adapter, A_SG_CONTEXT_DATA0, base_addr); - base_addr >>= 32; - t3_write_reg(adapter, A_SG_CONTEXT_DATA1, - V_FL_BASE_HI((u32) base_addr) | - V_FL_INDEX_LO(cidx & M_FL_INDEX_LO)); - t3_write_reg(adapter, A_SG_CONTEXT_DATA2, V_FL_SIZE(size) | - V_FL_GEN(gen) | V_FL_INDEX_HI(cidx >> 12) | - V_FL_ENTRY_SIZE_LO(bsize & M_FL_ENTRY_SIZE_LO)); - t3_write_reg(adapter, A_SG_CONTEXT_DATA3, - V_FL_ENTRY_SIZE_HI(bsize >> (32 - S_FL_ENTRY_SIZE_LO)) | - V_FL_CONG_THRES(cong_thres) | V_FL_GTS(gts_enable)); - return t3_sge_write_context(adapter, id, F_FREELIST); -} - -/** - * t3_sge_init_rspcntxt - initialize an SGE response queue context - * @adapter: the adapter to configure - * @id: the context id - * @irq_vec_idx: MSI-X interrupt vector index, 0 if no MSI-X, -1 if no IRQ - * @base_addr: base address of queue - * @size: number of queue entries - * @fl_thres: threshold for selecting the normal or jumbo free list - * @gen: initial generation value for the context - * @cidx: consumer pointer - * - * Initialize an SGE response queue context and make it ready for use. - * The caller is responsible for ensuring only one context operation - * occurs at a time. - */ -int t3_sge_init_rspcntxt(struct adapter *adapter, unsigned int id, - int irq_vec_idx, u64 base_addr, unsigned int size, - unsigned int fl_thres, int gen, unsigned int cidx) -{ - unsigned int intr = 0; - - if (base_addr & 0xfff) /* must be 4K aligned */ - return -EINVAL; - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - base_addr >>= 12; - t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_CQ_SIZE(size) | - V_CQ_INDEX(cidx)); - t3_write_reg(adapter, A_SG_CONTEXT_DATA1, base_addr); - base_addr >>= 32; - if (irq_vec_idx >= 0) - intr = V_RQ_MSI_VEC(irq_vec_idx) | F_RQ_INTR_EN; - t3_write_reg(adapter, A_SG_CONTEXT_DATA2, - V_CQ_BASE_HI((u32) base_addr) | intr | V_RQ_GEN(gen)); - t3_write_reg(adapter, A_SG_CONTEXT_DATA3, fl_thres); - return t3_sge_write_context(adapter, id, F_RESPONSEQ); -} - -/** - * t3_sge_init_cqcntxt - initialize an SGE completion queue context - * @adapter: the adapter to configure - * @id: the context id - * @base_addr: base address of queue - * @size: number of queue entries - * @rspq: response queue for async notifications - * @ovfl_mode: CQ overflow mode - * @credits: completion queue credits - * @credit_thres: the credit threshold - * - * Initialize an SGE completion queue context and make it ready for use. - * The caller is responsible for ensuring only one context operation - * occurs at a time. - */ -int t3_sge_init_cqcntxt(struct adapter *adapter, unsigned int id, u64 base_addr, - unsigned int size, int rspq, int ovfl_mode, - unsigned int credits, unsigned int credit_thres) -{ - if (base_addr & 0xfff) /* must be 4K aligned */ - return -EINVAL; - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - base_addr >>= 12; - t3_write_reg(adapter, A_SG_CONTEXT_DATA0, V_CQ_SIZE(size)); - t3_write_reg(adapter, A_SG_CONTEXT_DATA1, base_addr); - base_addr >>= 32; - t3_write_reg(adapter, A_SG_CONTEXT_DATA2, - V_CQ_BASE_HI((u32) base_addr) | V_CQ_RSPQ(rspq) | - V_CQ_GEN(1) | V_CQ_OVERFLOW_MODE(ovfl_mode)); - t3_write_reg(adapter, A_SG_CONTEXT_DATA3, V_CQ_CREDITS(credits) | - V_CQ_CREDIT_THRES(credit_thres)); - return t3_sge_write_context(adapter, id, F_CQ); -} - -/** - * t3_sge_enable_ecntxt - enable/disable an SGE egress context - * @adapter: the adapter - * @id: the egress context id - * @enable: enable (1) or disable (0) the context - * - * Enable or disable an SGE egress context. The caller is responsible for - * ensuring only one context operation occurs at a time. - */ -int t3_sge_enable_ecntxt(struct adapter *adapter, unsigned int id, int enable) -{ - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0); - t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0); - t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0); - t3_write_reg(adapter, A_SG_CONTEXT_MASK3, F_EC_VALID); - t3_write_reg(adapter, A_SG_CONTEXT_DATA3, V_EC_VALID(enable)); - t3_write_reg(adapter, A_SG_CONTEXT_CMD, - V_CONTEXT_CMD_OPCODE(1) | F_EGRESS | V_CONTEXT(id)); - return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); -} - -/** - * t3_sge_disable_fl - disable an SGE free-buffer list - * @adapter: the adapter - * @id: the free list context id - * - * Disable an SGE free-buffer list. The caller is responsible for - * ensuring only one context operation occurs at a time. - */ -int t3_sge_disable_fl(struct adapter *adapter, unsigned int id) -{ - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - t3_write_reg(adapter, A_SG_CONTEXT_MASK0, 0); - t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0); - t3_write_reg(adapter, A_SG_CONTEXT_MASK2, V_FL_SIZE(M_FL_SIZE)); - t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0); - t3_write_reg(adapter, A_SG_CONTEXT_DATA2, 0); - t3_write_reg(adapter, A_SG_CONTEXT_CMD, - V_CONTEXT_CMD_OPCODE(1) | F_FREELIST | V_CONTEXT(id)); - return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); -} - -/** - * t3_sge_disable_rspcntxt - disable an SGE response queue - * @adapter: the adapter - * @id: the response queue context id - * - * Disable an SGE response queue. The caller is responsible for - * ensuring only one context operation occurs at a time. - */ -int t3_sge_disable_rspcntxt(struct adapter *adapter, unsigned int id) -{ - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - t3_write_reg(adapter, A_SG_CONTEXT_MASK0, V_CQ_SIZE(M_CQ_SIZE)); - t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0); - t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0); - t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0); - t3_write_reg(adapter, A_SG_CONTEXT_DATA0, 0); - t3_write_reg(adapter, A_SG_CONTEXT_CMD, - V_CONTEXT_CMD_OPCODE(1) | F_RESPONSEQ | V_CONTEXT(id)); - return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); -} - -/** - * t3_sge_disable_cqcntxt - disable an SGE completion queue - * @adapter: the adapter - * @id: the completion queue context id - * - * Disable an SGE completion queue. The caller is responsible for - * ensuring only one context operation occurs at a time. - */ -int t3_sge_disable_cqcntxt(struct adapter *adapter, unsigned int id) -{ - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - t3_write_reg(adapter, A_SG_CONTEXT_MASK0, V_CQ_SIZE(M_CQ_SIZE)); - t3_write_reg(adapter, A_SG_CONTEXT_MASK1, 0); - t3_write_reg(adapter, A_SG_CONTEXT_MASK2, 0); - t3_write_reg(adapter, A_SG_CONTEXT_MASK3, 0); - t3_write_reg(adapter, A_SG_CONTEXT_DATA0, 0); - t3_write_reg(adapter, A_SG_CONTEXT_CMD, - V_CONTEXT_CMD_OPCODE(1) | F_CQ | V_CONTEXT(id)); - return t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1); -} - -/** - * t3_sge_cqcntxt_op - perform an operation on a completion queue context - * @adapter: the adapter - * @id: the context id - * @op: the operation to perform - * - * Perform the selected operation on an SGE completion queue context. - * The caller is responsible for ensuring only one context operation - * occurs at a time. - */ -int t3_sge_cqcntxt_op(struct adapter *adapter, unsigned int id, unsigned int op, - unsigned int credits) -{ - u32 val; - - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - t3_write_reg(adapter, A_SG_CONTEXT_DATA0, credits << 16); - t3_write_reg(adapter, A_SG_CONTEXT_CMD, V_CONTEXT_CMD_OPCODE(op) | - V_CONTEXT(id) | F_CQ); - if (t3_wait_op_done_val(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, - 0, 5, 1, &val)) - return -EIO; - - if (op >= 2 && op < 7) { - if (adapter->params.rev > 0) - return G_CQ_INDEX(val); - - t3_write_reg(adapter, A_SG_CONTEXT_CMD, - V_CONTEXT_CMD_OPCODE(0) | F_CQ | V_CONTEXT(id)); - if (t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, - F_CONTEXT_CMD_BUSY, 0, 5, 1)) - return -EIO; - return G_CQ_INDEX(t3_read_reg(adapter, A_SG_CONTEXT_DATA0)); - } - return 0; -} - -/** - * t3_sge_read_context - read an SGE context - * @type: the context type - * @adapter: the adapter - * @id: the context id - * @data: holds the retrieved context - * - * Read an SGE egress context. The caller is responsible for ensuring - * only one context operation occurs at a time. - */ -static int t3_sge_read_context(unsigned int type, struct adapter *adapter, - unsigned int id, u32 data[4]) -{ - if (t3_read_reg(adapter, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY) - return -EBUSY; - - t3_write_reg(adapter, A_SG_CONTEXT_CMD, - V_CONTEXT_CMD_OPCODE(0) | type | V_CONTEXT(id)); - if (t3_wait_op_done(adapter, A_SG_CONTEXT_CMD, F_CONTEXT_CMD_BUSY, 0, - 5, 1)) - return -EIO; - data[0] = t3_read_reg(adapter, A_SG_CONTEXT_DATA0); - data[1] = t3_read_reg(adapter, A_SG_CONTEXT_DATA1); - data[2] = t3_read_reg(adapter, A_SG_CONTEXT_DATA2); - data[3] = t3_read_reg(adapter, A_SG_CONTEXT_DATA3); - return 0; -} - -/** - * t3_sge_read_ecntxt - read an SGE egress context - * @adapter: the adapter - * @id: the context id - * @data: holds the retrieved context - * - * Read an SGE egress context. The caller is responsible for ensuring - * only one context operation occurs at a time. - */ -int t3_sge_read_ecntxt(struct adapter *adapter, unsigned int id, u32 data[4]) -{ - if (id >= 65536) - return -EINVAL; - return t3_sge_read_context(F_EGRESS, adapter, id, data); -} - -/** - * t3_sge_read_cq - read an SGE CQ context - * @adapter: the adapter - * @id: the context id - * @data: holds the retrieved context - * - * Read an SGE CQ context. The caller is responsible for ensuring - * only one context operation occurs at a time. - */ -int t3_sge_read_cq(struct adapter *adapter, unsigned int id, u32 data[4]) -{ - if (id >= 65536) - return -EINVAL; - return t3_sge_read_context(F_CQ, adapter, id, data); -} - -/** - * t3_sge_read_fl - read an SGE free-list context - * @adapter: the adapter - * @id: the context id - * @data: holds the retrieved context - * - * Read an SGE free-list context. The caller is responsible for ensuring - * only one context operation occurs at a time. - */ -int t3_sge_read_fl(struct adapter *adapter, unsigned int id, u32 data[4]) -{ - if (id >= SGE_QSETS * 2) - return -EINVAL; - return t3_sge_read_context(F_FREELIST, adapter, id, data); -} - -/** - * t3_sge_read_rspq - read an SGE response queue context - * @adapter: the adapter - * @id: the context id - * @data: holds the retrieved context - * - * Read an SGE response queue context. The caller is responsible for - * ensuring only one context operation occurs at a time. - */ -int t3_sge_read_rspq(struct adapter *adapter, unsigned int id, u32 data[4]) -{ - if (id >= SGE_QSETS) - return -EINVAL; - return t3_sge_read_context(F_RESPONSEQ, adapter, id, data); -} - -/** - * t3_config_rss - configure Rx packet steering - * @adapter: the adapter - * @rss_config: RSS settings (written to TP_RSS_CONFIG) - * @cpus: values for the CPU lookup table (0xff terminated) - * @rspq: values for the response queue lookup table (0xffff terminated) - * - * Programs the receive packet steering logic. @cpus and @rspq provide - * the values for the CPU and response queue lookup tables. If they - * provide fewer values than the size of the tables the supplied values - * are used repeatedly until the tables are fully populated. - */ -void t3_config_rss(struct adapter *adapter, unsigned int rss_config, - const u8 * cpus, const u16 *rspq) -{ - int i, j, cpu_idx = 0, q_idx = 0; - - if (cpus) - for (i = 0; i < RSS_TABLE_SIZE; ++i) { - u32 val = i << 16; - - for (j = 0; j < 2; ++j) { - val |= (cpus[cpu_idx++] & 0x3f) << (8 * j); - if (cpus[cpu_idx] == 0xff) - cpu_idx = 0; - } - t3_write_reg(adapter, A_TP_RSS_LKP_TABLE, val); - } - - if (rspq) - for (i = 0; i < RSS_TABLE_SIZE; ++i) { - t3_write_reg(adapter, A_TP_RSS_MAP_TABLE, - (i << 16) | rspq[q_idx++]); - if (rspq[q_idx] == 0xffff) - q_idx = 0; - } - - t3_write_reg(adapter, A_TP_RSS_CONFIG, rss_config); -} - -/** - * t3_read_rss - read the contents of the RSS tables - * @adapter: the adapter - * @lkup: holds the contents of the RSS lookup table - * @map: holds the contents of the RSS map table - * - * Reads the contents of the receive packet steering tables. - */ -int t3_read_rss(struct adapter *adapter, u8 * lkup, u16 *map) -{ - int i; - u32 val; - - if (lkup) - for (i = 0; i < RSS_TABLE_SIZE; ++i) { - t3_write_reg(adapter, A_TP_RSS_LKP_TABLE, - 0xffff0000 | i); - val = t3_read_reg(adapter, A_TP_RSS_LKP_TABLE); - if (!(val & 0x80000000)) - return -EAGAIN; - *lkup++ = val; - *lkup++ = (val >> 8); - } - - if (map) - for (i = 0; i < RSS_TABLE_SIZE; ++i) { - t3_write_reg(adapter, A_TP_RSS_MAP_TABLE, - 0xffff0000 | i); - val = t3_read_reg(adapter, A_TP_RSS_MAP_TABLE); - if (!(val & 0x80000000)) - return -EAGAIN; - *map++ = val; - } - return 0; -} - -/** - * t3_tp_set_offload_mode - put TP in NIC/offload mode - * @adap: the adapter - * @enable: 1 to select offload mode, 0 for regular NIC - * - * Switches TP to NIC/offload mode. - */ -void t3_tp_set_offload_mode(struct adapter *adap, int enable) -{ - if (is_offload(adap) || !enable) - t3_set_reg_field(adap, A_TP_IN_CONFIG, F_NICMODE, - V_NICMODE(!enable)); -} - -/** - * pm_num_pages - calculate the number of pages of the payload memory - * @mem_size: the size of the payload memory - * @pg_size: the size of each payload memory page - * - * Calculate the number of pages, each of the given size, that fit in a - * memory of the specified size, respecting the HW requirement that the - * number of pages must be a multiple of 24. - */ -static inline unsigned int pm_num_pages(unsigned int mem_size, - unsigned int pg_size) -{ - unsigned int n = mem_size / pg_size; - - return n - n % 24; -} - -#define mem_region(adap, start, size, reg) \ - t3_write_reg((adap), A_ ## reg, (start)); \ - start += size - -/* - * partition_mem - partition memory and configure TP memory settings - * @adap: the adapter - * @p: the TP parameters - * - * Partitions context and payload memory and configures TP's memory - * registers. - */ -static void partition_mem(struct adapter *adap, const struct tp_params *p) -{ - unsigned int m, pstructs, tids = t3_mc5_size(&adap->mc5); - unsigned int timers = 0, timers_shift = 22; - - if (adap->params.rev > 0) { - if (tids <= 16 * 1024) { - timers = 1; - timers_shift = 16; - } else if (tids <= 64 * 1024) { - timers = 2; - timers_shift = 18; - } else if (tids <= 256 * 1024) { - timers = 3; - timers_shift = 20; - } - } - - t3_write_reg(adap, A_TP_PMM_SIZE, - p->chan_rx_size | (p->chan_tx_size >> 16)); - - t3_write_reg(adap, A_TP_PMM_TX_BASE, 0); - t3_write_reg(adap, A_TP_PMM_TX_PAGE_SIZE, p->tx_pg_size); - t3_write_reg(adap, A_TP_PMM_TX_MAX_PAGE, p->tx_num_pgs); - t3_set_reg_field(adap, A_TP_PARA_REG3, V_TXDATAACKIDX(M_TXDATAACKIDX), - V_TXDATAACKIDX(fls(p->tx_pg_size) - 12)); - - t3_write_reg(adap, A_TP_PMM_RX_BASE, 0); - t3_write_reg(adap, A_TP_PMM_RX_PAGE_SIZE, p->rx_pg_size); - t3_write_reg(adap, A_TP_PMM_RX_MAX_PAGE, p->rx_num_pgs); - - pstructs = p->rx_num_pgs + p->tx_num_pgs; - /* Add a bit of headroom and make multiple of 24 */ - pstructs += 48; - pstructs -= pstructs % 24; - t3_write_reg(adap, A_TP_CMM_MM_MAX_PSTRUCT, pstructs); - - m = tids * TCB_SIZE; - mem_region(adap, m, (64 << 10) * 64, SG_EGR_CNTX_BADDR); - mem_region(adap, m, (64 << 10) * 64, SG_CQ_CONTEXT_BADDR); - t3_write_reg(adap, A_TP_CMM_TIMER_BASE, V_CMTIMERMAXNUM(timers) | m); - m += ((p->ntimer_qs - 1) << timers_shift) + (1 << 22); - mem_region(adap, m, pstructs * 64, TP_CMM_MM_BASE); - mem_region(adap, m, 64 * (pstructs / 24), TP_CMM_MM_PS_FLST_BASE); - mem_region(adap, m, 64 * (p->rx_num_pgs / 24), TP_CMM_MM_RX_FLST_BASE); - mem_region(adap, m, 64 * (p->tx_num_pgs / 24), TP_CMM_MM_TX_FLST_BASE); - - m = (m + 4095) & ~0xfff; - t3_write_reg(adap, A_CIM_SDRAM_BASE_ADDR, m); - t3_write_reg(adap, A_CIM_SDRAM_ADDR_SIZE, p->cm_size - m); - - tids = (p->cm_size - m - (3 << 20)) / 3072 - 32; - m = t3_mc5_size(&adap->mc5) - adap->params.mc5.nservers - - adap->params.mc5.nfilters - adap->params.mc5.nroutes; - if (tids < m) - adap->params.mc5.nservers += m - tids; -} - -static inline void tp_wr_indirect(struct adapter *adap, unsigned int addr, - u32 val) -{ - t3_write_reg(adap, A_TP_PIO_ADDR, addr); - t3_write_reg(adap, A_TP_PIO_DATA, val); -} - -static void tp_config(struct adapter *adap, const struct tp_params *p) -{ - t3_write_reg(adap, A_TP_GLOBAL_CONFIG, F_TXPACINGENABLE | F_PATHMTU | - F_IPCHECKSUMOFFLOAD | F_UDPCHECKSUMOFFLOAD | - F_TCPCHECKSUMOFFLOAD | V_IPTTL(64)); - t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) | - F_MTUENABLE | V_WINDOWSCALEMODE(1) | - V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1)); - t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) | - V_AUTOSTATE2(1) | V_AUTOSTATE1(0) | - V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) | - F_AUTOCAREFUL | F_AUTOENABLE | V_DACK_MODE(1)); - t3_set_reg_field(adap, A_TP_IN_CONFIG, F_IPV6ENABLE | F_NICMODE, - F_IPV6ENABLE | F_NICMODE); - t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814); - t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105); - t3_set_reg_field(adap, A_TP_PARA_REG6, - adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND, - 0); - - t3_set_reg_field(adap, A_TP_PC_CONFIG, - F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL, - F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE | - F_RXCONGESTIONMODE); - t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0); - - if (adap->params.rev > 0) { - tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE); - t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO, - F_TXPACEAUTO); - t3_set_reg_field(adap, A_TP_PC_CONFIG, F_LOCKTID, F_LOCKTID); - t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEAUTOSTRICT); - } else - t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED); - - t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212); - t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212); - t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212); -} - -/* Desired TP timer resolution in usec */ -#define TP_TMR_RES 50 - -/* TCP timer values in ms */ -#define TP_DACK_TIMER 50 -#define TP_RTO_MIN 250 - -/** - * tp_set_timers - set TP timing parameters - * @adap: the adapter to set - * @core_clk: the core clock frequency in Hz - * - * Set TP's timing parameters, such as the various timer resolutions and - * the TCP timer values. - */ -static void tp_set_timers(struct adapter *adap, unsigned int core_clk) -{ - unsigned int tre = fls(core_clk / (1000000 / TP_TMR_RES)) - 1; - unsigned int dack_re = fls(core_clk / 5000) - 1; /* 200us */ - unsigned int tstamp_re = fls(core_clk / 1000); /* 1ms, at least */ - unsigned int tps = core_clk >> tre; - - t3_write_reg(adap, A_TP_TIMER_RESOLUTION, V_TIMERRESOLUTION(tre) | - V_DELAYEDACKRESOLUTION(dack_re) | - V_TIMESTAMPRESOLUTION(tstamp_re)); - t3_write_reg(adap, A_TP_DACK_TIMER, - (core_clk >> dack_re) / (1000 / TP_DACK_TIMER)); - t3_write_reg(adap, A_TP_TCP_BACKOFF_REG0, 0x3020100); - t3_write_reg(adap, A_TP_TCP_BACKOFF_REG1, 0x7060504); - t3_write_reg(adap, A_TP_TCP_BACKOFF_REG2, 0xb0a0908); - t3_write_reg(adap, A_TP_TCP_BACKOFF_REG3, 0xf0e0d0c); - t3_write_reg(adap, A_TP_SHIFT_CNT, V_SYNSHIFTMAX(6) | - V_RXTSHIFTMAXR1(4) | V_RXTSHIFTMAXR2(15) | - V_PERSHIFTBACKOFFMAX(8) | V_PERSHIFTMAX(8) | - V_KEEPALIVEMAX(9)); - -#define SECONDS * tps - - t3_write_reg(adap, A_TP_MSL, adap->params.rev > 0 ? 0 : 2 SECONDS); - t3_write_reg(adap, A_TP_RXT_MIN, tps / (1000 / TP_RTO_MIN)); - t3_write_reg(adap, A_TP_RXT_MAX, 64 SECONDS); - t3_write_reg(adap, A_TP_PERS_MIN, 5 SECONDS); - t3_write_reg(adap, A_TP_PERS_MAX, 64 SECONDS); - t3_write_reg(adap, A_TP_KEEP_IDLE, 7200 SECONDS); - t3_write_reg(adap, A_TP_KEEP_INTVL, 75 SECONDS); - t3_write_reg(adap, A_TP_INIT_SRTT, 3 SECONDS); - t3_write_reg(adap, A_TP_FINWAIT2_TIMER, 600 SECONDS); - -#undef SECONDS -} - -/** - * t3_tp_set_coalescing_size - set receive coalescing size - * @adap: the adapter - * @size: the receive coalescing size - * @psh: whether a set PSH bit should deliver coalesced data - * - * Set the receive coalescing size and PSH bit handling. - */ -int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh) -{ - u32 val; - - if (size > MAX_RX_COALESCING_LEN) - return -EINVAL; - - val = t3_read_reg(adap, A_TP_PARA_REG3); - val &= ~(F_RXCOALESCEENABLE | F_RXCOALESCEPSHEN); - - if (size) { - val |= F_RXCOALESCEENABLE; - if (psh) - val |= F_RXCOALESCEPSHEN; - t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) | - V_MAXRXDATA(MAX_RX_COALESCING_LEN)); - } - t3_write_reg(adap, A_TP_PARA_REG3, val); - return 0; -} - -/** - * t3_tp_set_max_rxsize - set the max receive size - * @adap: the adapter - * @size: the max receive size - * - * Set TP's max receive size. This is the limit that applies when - * receive coalescing is disabled. - */ -void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size) -{ - t3_write_reg(adap, A_TP_PARA_REG7, - V_PMMAXXFERLEN0(size) | V_PMMAXXFERLEN1(size)); -} - -static void __devinit init_mtus(unsigned short mtus[]) -{ - /* - * See draft-mathis-plpmtud-00.txt for the values. The min is 88 so - * it can accomodate max size TCP/IP headers when SACK and timestamps - * are enabled and still have at least 8 bytes of payload. - */ - mtus[0] = 88; - mtus[1] = 256; - mtus[2] = 512; - mtus[3] = 576; - mtus[4] = 808; - mtus[5] = 1024; - mtus[6] = 1280; - mtus[7] = 1492; - mtus[8] = 1500; - mtus[9] = 2002; - mtus[10] = 2048; - mtus[11] = 4096; - mtus[12] = 4352; - mtus[13] = 8192; - mtus[14] = 9000; - mtus[15] = 9600; -} - -/* - * Initial congestion control parameters. - */ -static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b) -{ - a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1; - a[9] = 2; - a[10] = 3; - a[11] = 4; - a[12] = 5; - a[13] = 6; - a[14] = 7; - a[15] = 8; - a[16] = 9; - a[17] = 10; - a[18] = 14; - a[19] = 17; - a[20] = 21; - a[21] = 25; - a[22] = 30; - a[23] = 35; - a[24] = 45; - a[25] = 60; - a[26] = 80; - a[27] = 100; - a[28] = 200; - a[29] = 300; - a[30] = 400; - a[31] = 500; - - b[0] = b[1] = b[2] = b[3] = b[4] = b[5] = b[6] = b[7] = b[8] = 0; - b[9] = b[10] = 1; - b[11] = b[12] = 2; - b[13] = b[14] = b[15] = b[16] = 3; - b[17] = b[18] = b[19] = b[20] = b[21] = 4; - b[22] = b[23] = b[24] = b[25] = b[26] = b[27] = 5; - b[28] = b[29] = 6; - b[30] = b[31] = 7; -} - -/* The minimum additive increment value for the congestion control table */ -#define CC_MIN_INCR 2U - -/** - * t3_load_mtus - write the MTU and congestion control HW tables - * @adap: the adapter - * @mtus: the unrestricted values for the MTU table - * @alphs: the values for the congestion control alpha parameter - * @beta: the values for the congestion control beta parameter - * @mtu_cap: the maximum permitted effective MTU - * - * Write the MTU table with the supplied MTUs capping each at &mtu_cap. - * Update the high-speed congestion control table with the supplied alpha, - * beta, and MTUs. - */ -void t3_load_mtus(struct adapter *adap, unsigned short mtus[NMTUS], - unsigned short alpha[NCCTRL_WIN], - unsigned short beta[NCCTRL_WIN], unsigned short mtu_cap) -{ - static const unsigned int avg_pkts[NCCTRL_WIN] = { - 2, 6, 10, 14, 20, 28, 40, 56, 80, 112, 160, 224, 320, 448, 640, - 896, 1281, 1792, 2560, 3584, 5120, 7168, 10240, 14336, 20480, - 28672, 40960, 57344, 81920, 114688, 163840, 229376 - }; - - unsigned int i, w; - - for (i = 0; i < NMTUS; ++i) { - unsigned int mtu = min(mtus[i], mtu_cap); - unsigned int log2 = fls(mtu); - - if (!(mtu & ((1 << log2) >> 2))) /* round */ - log2--; - t3_write_reg(adap, A_TP_MTU_TABLE, - (i << 24) | (log2 << 16) | mtu); - - for (w = 0; w < NCCTRL_WIN; ++w) { - unsigned int inc; - - inc = max(((mtu - 40) * alpha[w]) / avg_pkts[w], - CC_MIN_INCR); - - t3_write_reg(adap, A_TP_CCTRL_TABLE, (i << 21) | - (w << 16) | (beta[w] << 13) | inc); - } - } -} - -/** - * t3_read_hw_mtus - returns the values in the HW MTU table - * @adap: the adapter - * @mtus: where to store the HW MTU values - * - * Reads the HW MTU table. - */ -void t3_read_hw_mtus(struct adapter *adap, unsigned short mtus[NMTUS]) -{ - int i; - - for (i = 0; i < NMTUS; ++i) { - unsigned int val; - - t3_write_reg(adap, A_TP_MTU_TABLE, 0xff000000 | i); - val = t3_read_reg(adap, A_TP_MTU_TABLE); - mtus[i] = val & 0x3fff; - } -} - -/** - * t3_get_cong_cntl_tab - reads the congestion control table - * @adap: the adapter - * @incr: where to store the alpha values - * - * Reads the additive increments programmed into the HW congestion - * control table. - */ -void t3_get_cong_cntl_tab(struct adapter *adap, - unsigned short incr[NMTUS][NCCTRL_WIN]) -{ - unsigned int mtu, w; - - for (mtu = 0; mtu < NMTUS; ++mtu) - for (w = 0; w < NCCTRL_WIN; ++w) { - t3_write_reg(adap, A_TP_CCTRL_TABLE, - 0xffff0000 | (mtu << 5) | w); - incr[mtu][w] = t3_read_reg(adap, A_TP_CCTRL_TABLE) & - 0x1fff; - } -} - -/** - * t3_tp_get_mib_stats - read TP's MIB counters - * @adap: the adapter - * @tps: holds the returned counter values - * - * Returns the values of TP's MIB counters. - */ -void t3_tp_get_mib_stats(struct adapter *adap, struct tp_mib_stats *tps) -{ - t3_read_indirect(adap, A_TP_MIB_INDEX, A_TP_MIB_RDATA, (u32 *) tps, - sizeof(*tps) / sizeof(u32), 0); -} - -#define ulp_region(adap, name, start, len) \ - t3_write_reg((adap), A_ULPRX_ ## name ## _LLIMIT, (start)); \ - t3_write_reg((adap), A_ULPRX_ ## name ## _ULIMIT, \ - (start) + (len) - 1); \ - start += len - -#define ulptx_region(adap, name, start, len) \ - t3_write_reg((adap), A_ULPTX_ ## name ## _LLIMIT, (start)); \ - t3_write_reg((adap), A_ULPTX_ ## name ## _ULIMIT, \ - (start) + (len) - 1) - -static void ulp_config(struct adapter *adap, const struct tp_params *p) -{ - unsigned int m = p->chan_rx_size; - - ulp_region(adap, ISCSI, m, p->chan_rx_size / 8); - ulp_region(adap, TDDP, m, p->chan_rx_size / 8); - ulptx_region(adap, TPT, m, p->chan_rx_size / 4); - ulp_region(adap, STAG, m, p->chan_rx_size / 4); - ulp_region(adap, RQ, m, p->chan_rx_size / 4); - ulptx_region(adap, PBL, m, p->chan_rx_size / 4); - ulp_region(adap, PBL, m, p->chan_rx_size / 4); - t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff); -} - -void t3_config_trace_filter(struct adapter *adapter, - const struct trace_params *tp, int filter_index, - int invert, int enable) -{ - u32 addr, key[4], mask[4]; - - key[0] = tp->sport | (tp->sip << 16); - key[1] = (tp->sip >> 16) | (tp->dport << 16); - key[2] = tp->dip; - key[3] = tp->proto | (tp->vlan << 8) | (tp->intf << 20); - - mask[0] = tp->sport_mask | (tp->sip_mask << 16); - mask[1] = (tp->sip_mask >> 16) | (tp->dport_mask << 16); - mask[2] = tp->dip_mask; - mask[3] = tp->proto_mask | (tp->vlan_mask << 8) | (tp->intf_mask << 20); - - if (invert) - key[3] |= (1 << 29); - if (enable) - key[3] |= (1 << 28); - - addr = filter_index ? A_TP_RX_TRC_KEY0 : A_TP_TX_TRC_KEY0; - tp_wr_indirect(adapter, addr++, key[0]); - tp_wr_indirect(adapter, addr++, mask[0]); - tp_wr_indirect(adapter, addr++, key[1]); - tp_wr_indirect(adapter, addr++, mask[1]); - tp_wr_indirect(adapter, addr++, key[2]); - tp_wr_indirect(adapter, addr++, mask[2]); - tp_wr_indirect(adapter, addr++, key[3]); - tp_wr_indirect(adapter, addr, mask[3]); - t3_read_reg(adapter, A_TP_PIO_DATA); -} - -/** - * t3_config_sched - configure a HW traffic scheduler - * @adap: the adapter - * @kbps: target rate in Kbps - * @sched: the scheduler index - * - * Configure a HW scheduler for the target rate - */ -int t3_config_sched(struct adapter *adap, unsigned int kbps, int sched) -{ - unsigned int v, tps, cpt, bpt, delta, mindelta = ~0; - unsigned int clk = adap->params.vpd.cclk * 1000; - unsigned int selected_cpt = 0, selected_bpt = 0; - - if (kbps > 0) { - kbps *= 125; /* -> bytes */ - for (cpt = 1; cpt <= 255; cpt++) { - tps = clk / cpt; - bpt = (kbps + tps / 2) / tps; - if (bpt > 0 && bpt <= 255) { - v = bpt * tps; - delta = v >= kbps ? v - kbps : kbps - v; - if (delta <= mindelta) { - mindelta = delta; - selected_cpt = cpt; - selected_bpt = bpt; - } - } else if (selected_cpt) - break; - } - if (!selected_cpt) - return -EINVAL; - } - t3_write_reg(adap, A_TP_TM_PIO_ADDR, - A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2); - v = t3_read_reg(adap, A_TP_TM_PIO_DATA); - if (sched & 1) - v = (v & 0xffff) | (selected_cpt << 16) | (selected_bpt << 24); - else - v = (v & 0xffff0000) | selected_cpt | (selected_bpt << 8); - t3_write_reg(adap, A_TP_TM_PIO_DATA, v); - return 0; -} - -static int tp_init(struct adapter *adap, const struct tp_params *p) -{ - int busy = 0; - - tp_config(adap, p); - t3_set_vlan_accel(adap, 3, 0); - - if (is_offload(adap)) { - tp_set_timers(adap, adap->params.vpd.cclk * 1000); - t3_write_reg(adap, A_TP_RESET, F_FLSTINITENABLE); - busy = t3_wait_op_done(adap, A_TP_RESET, F_FLSTINITENABLE, - 0, 1000, 5); - if (busy) - CH_ERR(adap, "TP initialization timed out\n"); - } - - if (!busy) - t3_write_reg(adap, A_TP_RESET, F_TPRESET); - return busy; -} - -int t3_mps_set_active_ports(struct adapter *adap, unsigned int port_mask) -{ - if (port_mask & ~((1 << adap->params.nports) - 1)) - return -EINVAL; - t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE | F_PORT0ACTIVE, - port_mask << S_PORT0ACTIVE); - return 0; -} - -/* - * Perform the bits of HW initialization that are dependent on the number - * of available ports. - */ -static void init_hw_for_avail_ports(struct adapter *adap, int nports) -{ - int i; - - if (nports == 1) { - t3_set_reg_field(adap, A_ULPRX_CTL, F_ROUND_ROBIN, 0); - t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0); - t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN | - F_PORT0ACTIVE | F_ENFORCEPKT); - t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000); - } else { - t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN); - t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB); - t3_write_reg(adap, A_ULPTX_DMA_WEIGHT, - V_D1_WEIGHT(16) | V_D0_WEIGHT(16)); - t3_write_reg(adap, A_MPS_CFG, F_TPTXPORT0EN | F_TPTXPORT1EN | - F_TPRXPORTEN | F_PORT0ACTIVE | F_PORT1ACTIVE | - F_ENFORCEPKT); - t3_write_reg(adap, A_PM1_TX_CFG, 0x80008000); - t3_set_reg_field(adap, A_TP_PC_CONFIG, 0, F_TXTOSQUEUEMAPMODE); - t3_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP, - V_TX_MOD_QUEUE_REQ_MAP(0xaa)); - for (i = 0; i < 16; i++) - t3_write_reg(adap, A_TP_TX_MOD_QUE_TABLE, - (i << 16) | 0x1010); - } -} - -static int calibrate_xgm(struct adapter *adapter) -{ - if (uses_xaui(adapter)) { - unsigned int v, i; - - for (i = 0; i < 5; ++i) { - t3_write_reg(adapter, A_XGM_XAUI_IMP, 0); - t3_read_reg(adapter, A_XGM_XAUI_IMP); - msleep(1); - v = t3_read_reg(adapter, A_XGM_XAUI_IMP); - if (!(v & (F_XGM_CALFAULT | F_CALBUSY))) { - t3_write_reg(adapter, A_XGM_XAUI_IMP, - V_XAUIIMP(G_CALIMP(v) >> 2)); - return 0; - } - } - CH_ERR(adapter, "MAC calibration failed\n"); - return -1; - } else { - t3_write_reg(adapter, A_XGM_RGMII_IMP, - V_RGMIIIMPPD(2) | V_RGMIIIMPPU(3)); - t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_XGM_IMPSETUPDATE, - F_XGM_IMPSETUPDATE); - } - return 0; -} - -static void calibrate_xgm_t3b(struct adapter *adapter) -{ - if (!uses_xaui(adapter)) { - t3_write_reg(adapter, A_XGM_RGMII_IMP, F_CALRESET | - F_CALUPDATE | V_RGMIIIMPPD(2) | V_RGMIIIMPPU(3)); - t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_CALRESET, 0); - t3_set_reg_field(adapter, A_XGM_RGMII_IMP, 0, - F_XGM_IMPSETUPDATE); - t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_XGM_IMPSETUPDATE, - 0); - t3_set_reg_field(adapter, A_XGM_RGMII_IMP, F_CALUPDATE, 0); - t3_set_reg_field(adapter, A_XGM_RGMII_IMP, 0, F_CALUPDATE); - } -} - -struct mc7_timing_params { - unsigned char ActToPreDly; - unsigned char ActToRdWrDly; - unsigned char PreCyc; - unsigned char RefCyc[5]; - unsigned char BkCyc; - unsigned char WrToRdDly; - unsigned char RdToWrDly; -}; - -/* - * Write a value to a register and check that the write completed. These - * writes normally complete in a cycle or two, so one read should suffice. - * The very first read exists to flush the posted write to the device. - */ -static int wrreg_wait(struct adapter *adapter, unsigned int addr, u32 val) -{ - t3_write_reg(adapter, addr, val); - t3_read_reg(adapter, addr); /* flush */ - if (!(t3_read_reg(adapter, addr) & F_BUSY)) - return 0; - CH_ERR(adapter, "write to MC7 register 0x%x timed out\n", addr); - return -EIO; -} - -static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type) -{ - static const unsigned int mc7_mode[] = { - 0x632, 0x642, 0x652, 0x432, 0x442 - }; - static const struct mc7_timing_params mc7_timings[] = { - {12, 3, 4, {20, 28, 34, 52, 0}, 15, 6, 4}, - {12, 4, 5, {20, 28, 34, 52, 0}, 16, 7, 4}, - {12, 5, 6, {20, 28, 34, 52, 0}, 17, 8, 4}, - {9, 3, 4, {15, 21, 26, 39, 0}, 12, 6, 4}, - {9, 4, 5, {15, 21, 26, 39, 0}, 13, 7, 4} - }; - - u32 val; - unsigned int width, density, slow, attempts; - struct adapter *adapter = mc7->adapter; - const struct mc7_timing_params *p = &mc7_timings[mem_type]; - - val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); - slow = val & F_SLOW; - width = G_WIDTH(val); - density = G_DEN(val); - - t3_write_reg(adapter, mc7->offset + A_MC7_CFG, val | F_IFEN); - val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); /* flush */ - msleep(1); - - if (!slow) { - t3_write_reg(adapter, mc7->offset + A_MC7_CAL, F_SGL_CAL_EN); - t3_read_reg(adapter, mc7->offset + A_MC7_CAL); - msleep(1); - if (t3_read_reg(adapter, mc7->offset + A_MC7_CAL) & - (F_BUSY | F_SGL_CAL_EN | F_CAL_FAULT)) { - CH_ERR(adapter, "%s MC7 calibration timed out\n", - mc7->name); - goto out_fail; - } - } - - t3_write_reg(adapter, mc7->offset + A_MC7_PARM, - V_ACTTOPREDLY(p->ActToPreDly) | - V_ACTTORDWRDLY(p->ActToRdWrDly) | V_PRECYC(p->PreCyc) | - V_REFCYC(p->RefCyc[density]) | V_BKCYC(p->BkCyc) | - V_WRTORDDLY(p->WrToRdDly) | V_RDTOWRDLY(p->RdToWrDly)); - - t3_write_reg(adapter, mc7->offset + A_MC7_CFG, - val | F_CLKEN | F_TERM150); - t3_read_reg(adapter, mc7->offset + A_MC7_CFG); /* flush */ - - if (!slow) - t3_set_reg_field(adapter, mc7->offset + A_MC7_DLL, F_DLLENB, - F_DLLENB); - udelay(1); - - val = slow ? 3 : 6; - if (wrreg_wait(adapter, mc7->offset + A_MC7_PRE, 0) || - wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE2, 0) || - wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE3, 0) || - wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val)) - goto out_fail; - - if (!slow) { - t3_write_reg(adapter, mc7->offset + A_MC7_MODE, 0x100); - t3_set_reg_field(adapter, mc7->offset + A_MC7_DLL, F_DLLRST, 0); - udelay(5); - } - - if (wrreg_wait(adapter, mc7->offset + A_MC7_PRE, 0) || - wrreg_wait(adapter, mc7->offset + A_MC7_REF, 0) || - wrreg_wait(adapter, mc7->offset + A_MC7_REF, 0) || - wrreg_wait(adapter, mc7->offset + A_MC7_MODE, - mc7_mode[mem_type]) || - wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val | 0x380) || - wrreg_wait(adapter, mc7->offset + A_MC7_EXT_MODE1, val)) - goto out_fail; - - /* clock value is in KHz */ - mc7_clock = mc7_clock * 7812 + mc7_clock / 2; /* ns */ - mc7_clock /= 1000000; /* KHz->MHz, ns->us */ - - t3_write_reg(adapter, mc7->offset + A_MC7_REF, - F_PERREFEN | V_PREREFDIV(mc7_clock)); - t3_read_reg(adapter, mc7->offset + A_MC7_REF); /* flush */ - - t3_write_reg(adapter, mc7->offset + A_MC7_ECC, F_ECCGENEN | F_ECCCHKEN); - t3_write_reg(adapter, mc7->offset + A_MC7_BIST_DATA, 0); - t3_write_reg(adapter, mc7->offset + A_MC7_BIST_ADDR_BEG, 0); - t3_write_reg(adapter, mc7->offset + A_MC7_BIST_ADDR_END, - (mc7->size << width) - 1); - t3_write_reg(adapter, mc7->offset + A_MC7_BIST_OP, V_OP(1)); - t3_read_reg(adapter, mc7->offset + A_MC7_BIST_OP); /* flush */ - - attempts = 50; - do { - msleep(250); - val = t3_read_reg(adapter, mc7->offset + A_MC7_BIST_OP); - } while ((val & F_BUSY) && --attempts); - if (val & F_BUSY) { - CH_ERR(adapter, "%s MC7 BIST timed out\n", mc7->name); - goto out_fail; - } - - /* Enable normal memory accesses. */ - t3_set_reg_field(adapter, mc7->offset + A_MC7_CFG, 0, F_RDY); - return 0; - -out_fail: - return -1; -} - -static void config_pcie(struct adapter *adap) -{ - static const u16 ack_lat[4][6] = { - {237, 416, 559, 1071, 2095, 4143}, - {128, 217, 289, 545, 1057, 2081}, - {73, 118, 154, 282, 538, 1050}, - {67, 107, 86, 150, 278, 534} - }; - static const u16 rpl_tmr[4][6] = { - {711, 1248, 1677, 3213, 6285, 12429}, - {384, 651, 867, 1635, 3171, 6243}, - {219, 354, 462, 846, 1614, 3150}, - {201, 321, 258, 450, 834, 1602} - }; - - u16 val; - unsigned int log2_width, pldsize; - unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt; - - pci_read_config_word(adap->pdev, - adap->params.pci.pcie_cap_addr + PCI_EXP_DEVCTL, - &val); - pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5; - pci_read_config_word(adap->pdev, - adap->params.pci.pcie_cap_addr + PCI_EXP_LNKCTL, - &val); - - fst_trn_tx = G_NUMFSTTRNSEQ(t3_read_reg(adap, A_PCIE_PEX_CTRL0)); - fst_trn_rx = adap->params.rev == 0 ? fst_trn_tx : - G_NUMFSTTRNSEQRX(t3_read_reg(adap, A_PCIE_MODE)); - log2_width = fls(adap->params.pci.width) - 1; - acklat = ack_lat[log2_width][pldsize]; - if (val & 1) /* check LOsEnable */ - acklat += fst_trn_tx * 4; - rpllmt = rpl_tmr[log2_width][pldsize] + fst_trn_rx * 4; - - if (adap->params.rev == 0) - t3_set_reg_field(adap, A_PCIE_PEX_CTRL1, - V_T3A_ACKLAT(M_T3A_ACKLAT), - V_T3A_ACKLAT(acklat)); - else - t3_set_reg_field(adap, A_PCIE_PEX_CTRL1, V_ACKLAT(M_ACKLAT), - V_ACKLAT(acklat)); - - t3_set_reg_field(adap, A_PCIE_PEX_CTRL0, V_REPLAYLMT(M_REPLAYLMT), - V_REPLAYLMT(rpllmt)); - - t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff); - t3_set_reg_field(adap, A_PCIE_CFG, F_PCIE_CLIDECEN, F_PCIE_CLIDECEN); -} - -/* - * Initialize and configure T3 HW modules. This performs the - * initialization steps that need to be done once after a card is reset. - * MAC and PHY initialization is handled separarely whenever a port is enabled. - * - * fw_params are passed to FW and their value is platform dependent. Only the - * top 8 bits are available for use, the rest must be 0. - */ -int t3_init_hw(struct adapter *adapter, u32 fw_params) -{ - int err = -EIO, attempts = 100; - const struct vpd_params *vpd = &adapter->params.vpd; - - if (adapter->params.rev > 0) - calibrate_xgm_t3b(adapter); - else if (calibrate_xgm(adapter)) - goto out_err; - - if (vpd->mclk) { - partition_mem(adapter, &adapter->params.tp); - - if (mc7_init(&adapter->pmrx, vpd->mclk, vpd->mem_timing) || - mc7_init(&adapter->pmtx, vpd->mclk, vpd->mem_timing) || - mc7_init(&adapter->cm, vpd->mclk, vpd->mem_timing) || - t3_mc5_init(&adapter->mc5, adapter->params.mc5.nservers, - adapter->params.mc5.nfilters, - adapter->params.mc5.nroutes)) - goto out_err; - } - - if (tp_init(adapter, &adapter->params.tp)) - goto out_err; - - t3_tp_set_coalescing_size(adapter, - min(adapter->params.sge.max_pkt_size, - MAX_RX_COALESCING_LEN), 1); - t3_tp_set_max_rxsize(adapter, - min(adapter->params.sge.max_pkt_size, 16384U)); - ulp_config(adapter, &adapter->params.tp); - - if (is_pcie(adapter)) - config_pcie(adapter); - else - t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN); - - t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000); - init_hw_for_avail_ports(adapter, adapter->params.nports); - t3_sge_init(adapter, &adapter->params.sge); - - t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params); - t3_write_reg(adapter, A_CIM_BOOT_CFG, - V_BOOTADDR(FW_FLASH_BOOT_ADDR >> 2)); - t3_read_reg(adapter, A_CIM_BOOT_CFG); /* flush */ - - do { /* wait for uP to initialize */ - msleep(20); - } while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts); - if (!attempts) - goto out_err; - - err = 0; -out_err: - return err; -} - -/** - * get_pci_mode - determine a card's PCI mode - * @adapter: the adapter - * @p: where to store the PCI settings - * - * Determines a card's PCI mode and associated parameters, such as speed - * and width. - */ -static void __devinit get_pci_mode(struct adapter *adapter, - struct pci_params *p) -{ - static unsigned short speed_map[] = { 33, 66, 100, 133 }; - u32 pci_mode, pcie_cap; - - pcie_cap = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); - if (pcie_cap) { - u16 val; - - p->variant = PCI_VARIANT_PCIE; - p->pcie_cap_addr = pcie_cap; - pci_read_config_word(adapter->pdev, pcie_cap + PCI_EXP_LNKSTA, - &val); - p->width = (val >> 4) & 0x3f; - return; - } - - pci_mode = t3_read_reg(adapter, A_PCIX_MODE); - p->speed = speed_map[G_PCLKRANGE(pci_mode)]; - p->width = (pci_mode & F_64BIT) ? 64 : 32; - pci_mode = G_PCIXINITPAT(pci_mode); - if (pci_mode == 0) - p->variant = PCI_VARIANT_PCI; - else if (pci_mode < 4) - p->variant = PCI_VARIANT_PCIX_MODE1_PARITY; - else if (pci_mode < 8) - p->variant = PCI_VARIANT_PCIX_MODE1_ECC; - else - p->variant = PCI_VARIANT_PCIX_266_MODE2; -} - -/** - * init_link_config - initialize a link's SW state - * @lc: structure holding the link state - * @ai: information about the current card - * - * Initializes the SW state maintained for each link, including the link's - * capabilities and default speed/duplex/flow-control/autonegotiation - * settings. - */ -static void __devinit init_link_config(struct link_config *lc, - unsigned int caps) -{ - lc->supported = caps; - lc->requested_speed = lc->speed = SPEED_INVALID; - lc->requested_duplex = lc->duplex = DUPLEX_INVALID; - lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX; - if (lc->supported & SUPPORTED_Autoneg) { - lc->advertising = lc->supported; - lc->autoneg = AUTONEG_ENABLE; - lc->requested_fc |= PAUSE_AUTONEG; - } else { - lc->advertising = 0; - lc->autoneg = AUTONEG_DISABLE; - } -} - -/** - * mc7_calc_size - calculate MC7 memory size - * @cfg: the MC7 configuration - * - * Calculates the size of an MC7 memory in bytes from the value of its - * configuration register. - */ -static unsigned int __devinit mc7_calc_size(u32 cfg) -{ - unsigned int width = G_WIDTH(cfg); - unsigned int banks = !!(cfg & F_BKS) + 1; - unsigned int org = !!(cfg & F_ORG) + 1; - unsigned int density = G_DEN(cfg); - unsigned int MBs = ((256 << density) * banks) / (org << width); - - return MBs << 20; -} - -static void __devinit mc7_prep(struct adapter *adapter, struct mc7 *mc7, - unsigned int base_addr, const char *name) -{ - u32 cfg; - - mc7->adapter = adapter; - mc7->name = name; - mc7->offset = base_addr - MC7_PMRX_BASE_ADDR; - cfg = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); - mc7->size = mc7_calc_size(cfg); - mc7->width = G_WIDTH(cfg); -} - -void mac_prep(struct cmac *mac, struct adapter *adapter, int index) -{ - mac->adapter = adapter; - mac->offset = (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR) * index; - mac->nucast = 1; - - if (adapter->params.rev == 0 && uses_xaui(adapter)) { - t3_write_reg(adapter, A_XGM_SERDES_CTRL + mac->offset, - is_10G(adapter) ? 0x2901c04 : 0x2301c04); - t3_set_reg_field(adapter, A_XGM_PORT_CFG + mac->offset, - F_ENRGMII, 0); - } -} - -void early_hw_init(struct adapter *adapter, const struct adapter_info *ai) -{ - u32 val = V_PORTSPEED(is_10G(adapter) ? 3 : 2); - - mi1_init(adapter, ai); - t3_write_reg(adapter, A_I2C_CFG, /* set for 80KHz */ - V_I2C_CLKDIV(adapter->params.vpd.cclk / 80 - 1)); - t3_write_reg(adapter, A_T3DBG_GPIO_EN, - ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL); - - if (adapter->params.rev == 0 || !uses_xaui(adapter)) - val |= F_ENRGMII; - - /* Enable MAC clocks so we can access the registers */ - t3_write_reg(adapter, A_XGM_PORT_CFG, val); - t3_read_reg(adapter, A_XGM_PORT_CFG); - - val |= F_CLKDIVRESET_; - t3_write_reg(adapter, A_XGM_PORT_CFG, val); - t3_read_reg(adapter, A_XGM_PORT_CFG); - t3_write_reg(adapter, XGM_REG(A_XGM_PORT_CFG, 1), val); - t3_read_reg(adapter, A_XGM_PORT_CFG); -} - -/* - * Reset the adapter. PCIe cards lose their config space during reset, PCI-X - * ones don't. - */ -int t3_reset_adapter(struct adapter *adapter) -{ - int i; - uint16_t devid = 0; - - if (is_pcie(adapter)) - pci_save_state(adapter->pdev); - t3_write_reg(adapter, A_PL_RST, F_CRSTWRM | F_CRSTWRMMODE); - - /* - * Delay. Give Some time to device to reset fully. - * XXX The delay time should be modified. - */ - for (i = 0; i < 10; i++) { - msleep(50); - pci_read_config_word(adapter->pdev, 0x00, &devid); - if (devid == 0x1425) - break; - } - - if (devid != 0x1425) - return -1; - - if (is_pcie(adapter)) - pci_restore_state(adapter->pdev); - return 0; -} - -/* - * Initialize adapter SW state for the various HW modules, set initial values - * for some adapter tunables, take PHYs out of reset, and initialize the MDIO - * interface. - */ -int __devinit t3_prep_adapter(struct adapter *adapter, - const struct adapter_info *ai, int reset) -{ - int ret; - unsigned int i, j = 0; - - get_pci_mode(adapter, &adapter->params.pci); - - adapter->params.info = ai; - adapter->params.nports = ai->nports; - adapter->params.rev = t3_read_reg(adapter, A_PL_REV); - adapter->params.linkpoll_period = 0; - adapter->params.stats_update_period = is_10G(adapter) ? - MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10); - adapter->params.pci.vpd_cap_addr = - pci_find_capability(adapter->pdev, PCI_CAP_ID_VPD); - ret = get_vpd_params(adapter, &adapter->params.vpd); - if (ret < 0) - return ret; - - if (reset && t3_reset_adapter(adapter)) - return -1; - - t3_sge_prep(adapter, &adapter->params.sge); - - if (adapter->params.vpd.mclk) { - struct tp_params *p = &adapter->params.tp; - - mc7_prep(adapter, &adapter->pmrx, MC7_PMRX_BASE_ADDR, "PMRX"); - mc7_prep(adapter, &adapter->pmtx, MC7_PMTX_BASE_ADDR, "PMTX"); - mc7_prep(adapter, &adapter->cm, MC7_CM_BASE_ADDR, "CM"); - - p->nchan = ai->nports; - p->pmrx_size = t3_mc7_size(&adapter->pmrx); - p->pmtx_size = t3_mc7_size(&adapter->pmtx); - p->cm_size = t3_mc7_size(&adapter->cm); - p->chan_rx_size = p->pmrx_size / 2; /* only 1 Rx channel */ - p->chan_tx_size = p->pmtx_size / p->nchan; - p->rx_pg_size = 64 * 1024; - p->tx_pg_size = is_10G(adapter) ? 64 * 1024 : 16 * 1024; - p->rx_num_pgs = pm_num_pages(p->chan_rx_size, p->rx_pg_size); - p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size); - p->ntimer_qs = p->cm_size >= (128 << 20) || - adapter->params.rev > 0 ? 12 : 6; - - adapter->params.mc5.nservers = DEFAULT_NSERVERS; - adapter->params.mc5.nfilters = adapter->params.rev > 0 ? - DEFAULT_NFILTERS : 0; - adapter->params.mc5.nroutes = 0; - t3_mc5_prep(adapter, &adapter->mc5, MC5_MODE_144_BIT); - - init_mtus(adapter->params.mtus); - init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd); - } - - early_hw_init(adapter, ai); - - for_each_port(adapter, i) { - u8 hw_addr[6]; - struct port_info *p = adap2pinfo(adapter, i); - - while (!adapter->params.vpd.port_type[j]) - ++j; - - p->port_type = &port_types[adapter->params.vpd.port_type[j]]; - p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, - ai->mdio_ops); - mac_prep(&p->mac, adapter, j); - ++j; - - /* - * The VPD EEPROM stores the base Ethernet address for the - * card. A port's address is derived from the base by adding - * the port's index to the base's low octet. - */ - memcpy(hw_addr, adapter->params.vpd.eth_base, 5); - hw_addr[5] = adapter->params.vpd.eth_base[5] + i; - - memcpy(adapter->port[i]->dev_addr, hw_addr, - ETH_ALEN); - memcpy(adapter->port[i]->perm_addr, hw_addr, - ETH_ALEN); - init_link_config(&p->link_config, p->port_type->caps); - p->phy.ops->power_down(&p->phy, 1); - if (!(p->port_type->caps & SUPPORTED_IRQ)) - adapter->params.linkpoll_period = 10; - } - - return 0; -} - -void t3_led_ready(struct adapter *adapter) -{ - t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, - F_GPIO0_OUT_VAL); -} diff --git a/trunk/drivers/net/cxgb3/t3cdev.h b/trunk/drivers/net/cxgb3/t3cdev.h deleted file mode 100644 index 9af3bcd64b3b..000000000000 --- a/trunk/drivers/net/cxgb3/t3cdev.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2006-2007 Chelsio Communications. All rights reserved. - * Copyright (C) 2006-2007 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _T3CDEV_H_ -#define _T3CDEV_H_ - -#include -#include -#include -#include -#include -#include -#include - -#define T3CNAMSIZ 16 - -/* Get the t3cdev associated with a net_device */ -#define T3CDEV(netdev) (struct t3cdev *)(netdev->priv) - -struct cxgb3_client; - -enum t3ctype { - T3A = 0, - T3B -}; - -struct t3cdev { - char name[T3CNAMSIZ]; /* T3C device name */ - enum t3ctype type; - struct list_head ofld_dev_list; /* for list linking */ - struct net_device *lldev; /* LL dev associated with T3C messages */ - struct proc_dir_entry *proc_dir; /* root of proc dir for this T3C */ - int (*send)(struct t3cdev *dev, struct sk_buff *skb); - int (*recv)(struct t3cdev *dev, struct sk_buff **skb, int n); - int (*ctl)(struct t3cdev *dev, unsigned int req, void *data); - void (*neigh_update)(struct t3cdev *dev, struct neighbour *neigh); - void *priv; /* driver private data */ - void *l2opt; /* optional layer 2 data */ - void *l3opt; /* optional layer 3 data */ - void *l4opt; /* optional layer 4 data */ - void *ulp; /* ulp stuff */ -}; - -#endif /* _T3CDEV_H_ */ diff --git a/trunk/drivers/net/cxgb3/version.h b/trunk/drivers/net/cxgb3/version.h deleted file mode 100644 index 2b67dd523cc1..000000000000 --- a/trunk/drivers/net/cxgb3/version.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2003-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -/* $Date: 2006/10/31 18:57:51 $ $RCSfile: version.h,v $ $Revision: 1.3 $ */ -#ifndef __CHELSIO_VERSION_H -#define __CHELSIO_VERSION_H -#define DRV_DESC "Chelsio T3 Network Driver" -#define DRV_NAME "cxgb3" -/* Driver version */ -#define DRV_VERSION "1.0" -#endif /* __CHELSIO_VERSION_H */ diff --git a/trunk/drivers/net/cxgb3/vsc8211.c b/trunk/drivers/net/cxgb3/vsc8211.c deleted file mode 100644 index eee4285b31be..000000000000 --- a/trunk/drivers/net/cxgb3/vsc8211.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "common.h" - -/* VSC8211 PHY specific registers. */ -enum { - VSC8211_INTR_ENABLE = 25, - VSC8211_INTR_STATUS = 26, - VSC8211_AUX_CTRL_STAT = 28, -}; - -enum { - VSC_INTR_RX_ERR = 1 << 0, - VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */ - VSC_INTR_CABLE = 1 << 2, /* cable impairment */ - VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */ - VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */ - VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */ - VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */ - VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */ - VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */ - VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */ - VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */ - VSC_INTR_LINK_CHG = 1 << 13, /* link change */ - VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */ -}; - -#define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \ - VSC_INTR_NEG_DONE) -#define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \ - VSC_INTR_ENABLE) - -/* PHY specific auxiliary control & status register fields */ -#define S_ACSR_ACTIPHY_TMR 0 -#define M_ACSR_ACTIPHY_TMR 0x3 -#define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR) - -#define S_ACSR_SPEED 3 -#define M_ACSR_SPEED 0x3 -#define G_ACSR_SPEED(x) (((x) >> S_ACSR_SPEED) & M_ACSR_SPEED) - -#define S_ACSR_DUPLEX 5 -#define F_ACSR_DUPLEX (1 << S_ACSR_DUPLEX) - -#define S_ACSR_ACTIPHY 6 -#define F_ACSR_ACTIPHY (1 << S_ACSR_ACTIPHY) - -/* - * Reset the PHY. This PHY completes reset immediately so we never wait. - */ -static int vsc8211_reset(struct cphy *cphy, int wait) -{ - return t3_phy_reset(cphy, 0, 0); -} - -static int vsc8211_intr_enable(struct cphy *cphy) -{ - return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, INTR_MASK); -} - -static int vsc8211_intr_disable(struct cphy *cphy) -{ - return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, 0); -} - -static int vsc8211_intr_clear(struct cphy *cphy) -{ - u32 val; - - /* Clear PHY interrupts by reading the register. */ - return mdio_read(cphy, 0, VSC8211_INTR_STATUS, &val); -} - -static int vsc8211_autoneg_enable(struct cphy *cphy) -{ - return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, - BMCR_ANENABLE | BMCR_ANRESTART); -} - -static int vsc8211_autoneg_restart(struct cphy *cphy) -{ - return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, - BMCR_ANRESTART); -} - -static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, - int *speed, int *duplex, int *fc) -{ - unsigned int bmcr, status, lpa, adv; - int err, sp = -1, dplx = -1, pause = 0; - - err = mdio_read(cphy, 0, MII_BMCR, &bmcr); - if (!err) - err = mdio_read(cphy, 0, MII_BMSR, &status); - if (err) - return err; - - if (link_ok) { - /* - * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it - * once more to get the current link state. - */ - if (!(status & BMSR_LSTATUS)) - err = mdio_read(cphy, 0, MII_BMSR, &status); - if (err) - return err; - *link_ok = (status & BMSR_LSTATUS) != 0; - } - if (!(bmcr & BMCR_ANENABLE)) { - dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; - if (bmcr & BMCR_SPEED1000) - sp = SPEED_1000; - else if (bmcr & BMCR_SPEED100) - sp = SPEED_100; - else - sp = SPEED_10; - } else if (status & BMSR_ANEGCOMPLETE) { - err = mdio_read(cphy, 0, VSC8211_AUX_CTRL_STAT, &status); - if (err) - return err; - - dplx = (status & F_ACSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF; - sp = G_ACSR_SPEED(status); - if (sp == 0) - sp = SPEED_10; - else if (sp == 1) - sp = SPEED_100; - else - sp = SPEED_1000; - - if (fc && dplx == DUPLEX_FULL) { - err = mdio_read(cphy, 0, MII_LPA, &lpa); - if (!err) - err = mdio_read(cphy, 0, MII_ADVERTISE, &adv); - if (err) - return err; - - if (lpa & adv & ADVERTISE_PAUSE_CAP) - pause = PAUSE_RX | PAUSE_TX; - else if ((lpa & ADVERTISE_PAUSE_CAP) && - (lpa & ADVERTISE_PAUSE_ASYM) && - (adv & ADVERTISE_PAUSE_ASYM)) - pause = PAUSE_TX; - else if ((lpa & ADVERTISE_PAUSE_ASYM) && - (adv & ADVERTISE_PAUSE_CAP)) - pause = PAUSE_RX; - } - } - if (speed) - *speed = sp; - if (duplex) - *duplex = dplx; - if (fc) - *fc = pause; - return 0; -} - -static int vsc8211_power_down(struct cphy *cphy, int enable) -{ - return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN, - enable ? BMCR_PDOWN : 0); -} - -static int vsc8211_intr_handler(struct cphy *cphy) -{ - unsigned int cause; - int err, cphy_cause = 0; - - err = mdio_read(cphy, 0, VSC8211_INTR_STATUS, &cause); - if (err) - return err; - - cause &= INTR_MASK; - if (cause & CFG_CHG_INTR_MASK) - cphy_cause |= cphy_cause_link_change; - if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO)) - cphy_cause |= cphy_cause_fifo_error; - return cphy_cause; -} - -static struct cphy_ops vsc8211_ops = { - .reset = vsc8211_reset, - .intr_enable = vsc8211_intr_enable, - .intr_disable = vsc8211_intr_disable, - .intr_clear = vsc8211_intr_clear, - .intr_handler = vsc8211_intr_handler, - .autoneg_enable = vsc8211_autoneg_enable, - .autoneg_restart = vsc8211_autoneg_restart, - .advertise = t3_phy_advertise, - .set_speed_duplex = t3_set_phy_speed_duplex, - .get_link_status = vsc8211_get_link_status, - .power_down = vsc8211_power_down, -}; - -void t3_vsc8211_phy_prep(struct cphy *phy, struct adapter *adapter, - int phy_addr, const struct mdio_ops *mdio_ops) -{ - cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops); -} diff --git a/trunk/drivers/net/cxgb3/xgmac.c b/trunk/drivers/net/cxgb3/xgmac.c deleted file mode 100644 index 907a272ae32d..000000000000 --- a/trunk/drivers/net/cxgb3/xgmac.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "common.h" -#include "regs.h" - -/* - * # of exact address filters. The first one is used for the station address, - * the rest are available for multicast addresses. - */ -#define EXACT_ADDR_FILTERS 8 - -static inline int macidx(const struct cmac *mac) -{ - return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR); -} - -static void xaui_serdes_reset(struct cmac *mac) -{ - static const unsigned int clear[] = { - F_PWRDN0 | F_PWRDN1, F_RESETPLL01, F_RESET0 | F_RESET1, - F_PWRDN2 | F_PWRDN3, F_RESETPLL23, F_RESET2 | F_RESET3 - }; - - int i; - struct adapter *adap = mac->adapter; - u32 ctrl = A_XGM_SERDES_CTRL0 + mac->offset; - - t3_write_reg(adap, ctrl, adap->params.vpd.xauicfg[macidx(mac)] | - F_RESET3 | F_RESET2 | F_RESET1 | F_RESET0 | - F_PWRDN3 | F_PWRDN2 | F_PWRDN1 | F_PWRDN0 | - F_RESETPLL23 | F_RESETPLL01); - t3_read_reg(adap, ctrl); - udelay(15); - - for (i = 0; i < ARRAY_SIZE(clear); i++) { - t3_set_reg_field(adap, ctrl, clear[i], 0); - udelay(15); - } -} - -void t3b_pcs_reset(struct cmac *mac) -{ - t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, - F_PCS_RESET_, 0); - udelay(20); - t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0, - F_PCS_RESET_); -} - -int t3_mac_reset(struct cmac *mac) -{ - static const struct addr_val_pair mac_reset_avp[] = { - {A_XGM_TX_CTRL, 0}, - {A_XGM_RX_CTRL, 0}, - {A_XGM_RX_CFG, F_DISPAUSEFRAMES | F_EN1536BFRAMES | - F_RMFCS | F_ENJUMBO | F_ENHASHMCAST}, - {A_XGM_RX_HASH_LOW, 0}, - {A_XGM_RX_HASH_HIGH, 0}, - {A_XGM_RX_EXACT_MATCH_LOW_1, 0}, - {A_XGM_RX_EXACT_MATCH_LOW_2, 0}, - {A_XGM_RX_EXACT_MATCH_LOW_3, 0}, - {A_XGM_RX_EXACT_MATCH_LOW_4, 0}, - {A_XGM_RX_EXACT_MATCH_LOW_5, 0}, - {A_XGM_RX_EXACT_MATCH_LOW_6, 0}, - {A_XGM_RX_EXACT_MATCH_LOW_7, 0}, - {A_XGM_RX_EXACT_MATCH_LOW_8, 0}, - {A_XGM_STAT_CTRL, F_CLRSTATS} - }; - u32 val; - struct adapter *adap = mac->adapter; - unsigned int oft = mac->offset; - - t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); - t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ - - t3_write_regs(adap, mac_reset_avp, ARRAY_SIZE(mac_reset_avp), oft); - t3_set_reg_field(adap, A_XGM_RXFIFO_CFG + oft, - F_RXSTRFRWRD | F_DISERRFRAMES, - uses_xaui(adap) ? 0 : F_RXSTRFRWRD); - - if (uses_xaui(adap)) { - if (adap->params.rev == 0) { - t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, - F_RXENABLE | F_TXENABLE); - if (t3_wait_op_done(adap, A_XGM_SERDES_STATUS1 + oft, - F_CMULOCK, 1, 5, 2)) { - CH_ERR(adap, - "MAC %d XAUI SERDES CMU lock failed\n", - macidx(mac)); - return -1; - } - t3_set_reg_field(adap, A_XGM_SERDES_CTRL + oft, 0, - F_SERDESRESET_); - } else - xaui_serdes_reset(mac); - } - - if (adap->params.rev > 0) - t3_write_reg(adap, A_XGM_PAUSE_TIMER + oft, 0xf000); - - val = F_MAC_RESET_; - if (is_10G(adap)) - val |= F_PCS_RESET_; - else if (uses_xaui(adap)) - val |= F_PCS_RESET_ | F_XG2G_RESET_; - else - val |= F_RGMII_RESET_ | F_XG2G_RESET_; - t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val); - t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ - if ((val & F_PCS_RESET_) && adap->params.rev) { - msleep(1); - t3b_pcs_reset(mac); - } - - memset(&mac->stats, 0, sizeof(mac->stats)); - return 0; -} - -/* - * Set the exact match register 'idx' to recognize the given Ethernet address. - */ -static void set_addr_filter(struct cmac *mac, int idx, const u8 * addr) -{ - u32 addr_lo, addr_hi; - unsigned int oft = mac->offset + idx * 8; - - addr_lo = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; - addr_hi = (addr[5] << 8) | addr[4]; - - t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1 + oft, addr_lo); - t3_write_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_HIGH_1 + oft, addr_hi); -} - -/* Set one of the station's unicast MAC addresses. */ -int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]) -{ - if (idx >= mac->nucast) - return -EINVAL; - set_addr_filter(mac, idx, addr); - return 0; -} - -/* - * Specify the number of exact address filters that should be reserved for - * unicast addresses. Caller should reload the unicast and multicast addresses - * after calling this. - */ -int t3_mac_set_num_ucast(struct cmac *mac, int n) -{ - if (n > EXACT_ADDR_FILTERS) - return -EINVAL; - mac->nucast = n; - return 0; -} - -/* Calculate the RX hash filter index of an Ethernet address */ -static int hash_hw_addr(const u8 * addr) -{ - int hash = 0, octet, bit, i = 0, c; - - for (octet = 0; octet < 6; ++octet) - for (c = addr[octet], bit = 0; bit < 8; c >>= 1, ++bit) { - hash ^= (c & 1) << i; - if (++i == 6) - i = 0; - } - return hash; -} - -int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm) -{ - u32 val, hash_lo, hash_hi; - struct adapter *adap = mac->adapter; - unsigned int oft = mac->offset; - - val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES; - if (rm->dev->flags & IFF_PROMISC) - val |= F_COPYALLFRAMES; - t3_write_reg(adap, A_XGM_RX_CFG + oft, val); - - if (rm->dev->flags & IFF_ALLMULTI) - hash_lo = hash_hi = 0xffffffff; - else { - u8 *addr; - int exact_addr_idx = mac->nucast; - - hash_lo = hash_hi = 0; - while ((addr = t3_get_next_mcaddr(rm))) - if (exact_addr_idx < EXACT_ADDR_FILTERS) - set_addr_filter(mac, exact_addr_idx++, addr); - else { - int hash = hash_hw_addr(addr); - - if (hash < 32) - hash_lo |= (1 << hash); - else - hash_hi |= (1 << (hash - 32)); - } - } - - t3_write_reg(adap, A_XGM_RX_HASH_LOW + oft, hash_lo); - t3_write_reg(adap, A_XGM_RX_HASH_HIGH + oft, hash_hi); - return 0; -} - -int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) -{ - int hwm, lwm; - unsigned int thres, v; - struct adapter *adap = mac->adapter; - - /* - * MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max - * packet size register includes header, but not FCS. - */ - mtu += 14; - if (mtu > MAX_FRAME_SIZE - 4) - return -EINVAL; - t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); - - /* - * Adjust the PAUSE frame watermarks. We always set the LWM, and the - * HWM only if flow-control is enabled. - */ - hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, MAC_RXFIFO_SIZE / 2U); - hwm = min(hwm, 3 * MAC_RXFIFO_SIZE / 4 + 1024); - lwm = hwm - 1024; - v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset); - v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM); - v |= V_RXFIFOPAUSELWM(lwm / 8); - if (G_RXFIFOPAUSEHWM(v)) - v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) | - V_RXFIFOPAUSEHWM(hwm / 8); - t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v); - - /* Adjust the TX FIFO threshold based on the MTU */ - thres = (adap->params.vpd.cclk * 1000) / 15625; - thres = (thres * mtu) / 1000; - if (is_10G(adap)) - thres /= 10; - thres = mtu > thres ? (mtu - thres + 7) / 8 : 0; - thres = max(thres, 8U); /* need at least 8 */ - t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset, - V_TXFIFOTHRESH(M_TXFIFOTHRESH), V_TXFIFOTHRESH(thres)); - return 0; -} - -int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc) -{ - u32 val; - struct adapter *adap = mac->adapter; - unsigned int oft = mac->offset; - - if (duplex >= 0 && duplex != DUPLEX_FULL) - return -EINVAL; - if (speed >= 0) { - if (speed == SPEED_10) - val = V_PORTSPEED(0); - else if (speed == SPEED_100) - val = V_PORTSPEED(1); - else if (speed == SPEED_1000) - val = V_PORTSPEED(2); - else if (speed == SPEED_10000) - val = V_PORTSPEED(3); - else - return -EINVAL; - - t3_set_reg_field(adap, A_XGM_PORT_CFG + oft, - V_PORTSPEED(M_PORTSPEED), val); - } - - val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft); - val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM); - if (fc & PAUSE_TX) - val |= V_RXFIFOPAUSEHWM(G_RXFIFOPAUSELWM(val) + 128); /* +1KB */ - t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val); - - t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, - (fc & PAUSE_RX) ? F_TXPAUSEEN : 0); - return 0; -} - -int t3_mac_enable(struct cmac *mac, int which) -{ - int idx = macidx(mac); - struct adapter *adap = mac->adapter; - unsigned int oft = mac->offset; - - if (which & MAC_DIRECTION_TX) { - t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); - t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); - t3_write_reg(adap, A_TP_PIO_DATA, 0xbf000001); - t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); - t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); - } - if (which & MAC_DIRECTION_RX) - t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN); - return 0; -} - -int t3_mac_disable(struct cmac *mac, int which) -{ - int idx = macidx(mac); - struct adapter *adap = mac->adapter; - - if (which & MAC_DIRECTION_TX) { - t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); - t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); - t3_write_reg(adap, A_TP_PIO_DATA, 0xc000001f); - t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); - t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 0); - } - if (which & MAC_DIRECTION_RX) - t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); - return 0; -} - -/* - * This function is called periodically to accumulate the current values of the - * RMON counters into the port statistics. Since the packet counters are only - * 32 bits they can overflow in ~286 secs at 10G, so the function should be - * called more frequently than that. The byte counters are 45-bit wide, they - * would overflow in ~7.8 hours. - */ -const struct mac_stats *t3_mac_update_stats(struct cmac *mac) -{ -#define RMON_READ(mac, addr) t3_read_reg(mac->adapter, addr + mac->offset) -#define RMON_UPDATE(mac, name, reg) \ - (mac)->stats.name += (u64)RMON_READ(mac, A_XGM_STAT_##reg) -#define RMON_UPDATE64(mac, name, reg_lo, reg_hi) \ - (mac)->stats.name += RMON_READ(mac, A_XGM_STAT_##reg_lo) + \ - ((u64)RMON_READ(mac, A_XGM_STAT_##reg_hi) << 32) - - u32 v, lo; - - RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH); - RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH); - RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES); - RMON_UPDATE(mac, rx_bcast_frames, RX_BCAST_FRAMES); - RMON_UPDATE(mac, rx_fcs_errs, RX_CRC_ERR_FRAMES); - RMON_UPDATE(mac, rx_pause, RX_PAUSE_FRAMES); - RMON_UPDATE(mac, rx_jabber, RX_JABBER_FRAMES); - RMON_UPDATE(mac, rx_short, RX_SHORT_FRAMES); - RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES); - - RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES); - mac->stats.rx_too_long += RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT); - - RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES); - RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES); - RMON_UPDATE(mac, rx_frames_128_255, RX_128_255B_FRAMES); - RMON_UPDATE(mac, rx_frames_256_511, RX_256_511B_FRAMES); - RMON_UPDATE(mac, rx_frames_512_1023, RX_512_1023B_FRAMES); - RMON_UPDATE(mac, rx_frames_1024_1518, RX_1024_1518B_FRAMES); - RMON_UPDATE(mac, rx_frames_1519_max, RX_1519_MAXB_FRAMES); - - RMON_UPDATE64(mac, tx_octets, TX_BYTE_LOW, TX_BYTE_HIGH); - RMON_UPDATE64(mac, tx_frames, TX_FRAME_LOW, TX_FRAME_HIGH); - RMON_UPDATE(mac, tx_mcast_frames, TX_MCAST); - RMON_UPDATE(mac, tx_bcast_frames, TX_BCAST); - RMON_UPDATE(mac, tx_pause, TX_PAUSE); - /* This counts error frames in general (bad FCS, underrun, etc). */ - RMON_UPDATE(mac, tx_underrun, TX_ERR_FRAMES); - - RMON_UPDATE(mac, tx_frames_64, TX_64B_FRAMES); - RMON_UPDATE(mac, tx_frames_65_127, TX_65_127B_FRAMES); - RMON_UPDATE(mac, tx_frames_128_255, TX_128_255B_FRAMES); - RMON_UPDATE(mac, tx_frames_256_511, TX_256_511B_FRAMES); - RMON_UPDATE(mac, tx_frames_512_1023, TX_512_1023B_FRAMES); - RMON_UPDATE(mac, tx_frames_1024_1518, TX_1024_1518B_FRAMES); - RMON_UPDATE(mac, tx_frames_1519_max, TX_1519_MAXB_FRAMES); - - /* The next stat isn't clear-on-read. */ - t3_write_reg(mac->adapter, A_TP_MIB_INDEX, mac->offset ? 51 : 50); - v = t3_read_reg(mac->adapter, A_TP_MIB_RDATA); - lo = (u32) mac->stats.rx_cong_drops; - mac->stats.rx_cong_drops += (u64) (v - lo); - - return &mac->stats; -} diff --git a/trunk/drivers/net/declance.c b/trunk/drivers/net/declance.c index 9f7e1db8ce62..4ae0fed7122e 100644 --- a/trunk/drivers/net/declance.c +++ b/trunk/drivers/net/declance.c @@ -5,7 +5,7 @@ * * adopted from sunlance.c by Richard van den Berg * - * Copyright (C) 2002, 2003, 2005, 2006 Maciej W. Rozycki + * Copyright (C) 2002, 2003, 2005 Maciej W. Rozycki * * additional sources: * - PMAD-AA TURBOchannel Ethernet Module Functional Specification, @@ -44,8 +44,6 @@ * v0.010: Fixes for the PMAD mapping of the LANCE buffer and for the * PMAX requirement to only use halfword accesses to the * buffer. macro - * - * v0.011: Converted the PMAD to the driver model. macro */ #include @@ -60,7 +58,6 @@ #include #include #include -#include #include #include @@ -72,16 +69,15 @@ #include #include #include +#include static char version[] __devinitdata = -"declance.c: v0.011 by Linux MIPS DECstation task force\n"; +"declance.c: v0.010 by Linux MIPS DECstation task force\n"; MODULE_AUTHOR("Linux MIPS DECstation task force"); MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver"); MODULE_LICENSE("GPL"); -#define __unused __attribute__ ((unused)) - /* * card types */ @@ -250,6 +246,7 @@ struct lance_init_block { struct lance_private { struct net_device *next; int type; + int slot; int dma_irq; volatile struct lance_regs *ll; @@ -291,7 +288,6 @@ struct lance_regs { int dec_lance_debug = 2; -static struct tc_driver dec_lance_tc_driver; static struct net_device *root_lance_dev; static inline void writereg(volatile unsigned short *regptr, short value) @@ -1027,7 +1023,7 @@ static void lance_set_multicast_retry(unsigned long _opaque) lance_set_multicast(dev); } -static int __init dec_lance_probe(struct device *bdev, const int type) +static int __init dec_lance_init(const int type, const int slot) { static unsigned version_printed; static const char fmt[] = "declance%d"; @@ -1035,7 +1031,6 @@ static int __init dec_lance_probe(struct device *bdev, const int type) struct net_device *dev; struct lance_private *lp; volatile struct lance_regs *ll; - resource_size_t start = 0, len = 0; int i, ret; unsigned long esar_base; unsigned char *esar; @@ -1043,18 +1038,14 @@ static int __init dec_lance_probe(struct device *bdev, const int type) if (dec_lance_debug && version_printed++ == 0) printk(version); - if (bdev) - snprintf(name, sizeof(name), "%s", bdev->bus_id); - else { - i = 0; - dev = root_lance_dev; - while (dev) { - i++; - lp = (struct lance_private *)dev->priv; - dev = lp->next; - } - snprintf(name, sizeof(name), fmt, i); + i = 0; + dev = root_lance_dev; + while (dev) { + i++; + lp = (struct lance_private *)dev->priv; + dev = lp->next; } + snprintf(name, sizeof(name), fmt, i); dev = alloc_etherdev(sizeof(struct lance_private)); if (!dev) { @@ -1072,6 +1063,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type) spin_lock_init(&lp->lock); lp->type = type; + lp->slot = slot; switch (type) { case ASIC_LANCE: dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE); @@ -1118,22 +1110,12 @@ static int __init dec_lance_probe(struct device *bdev, const int type) break; #ifdef CONFIG_TC case PMAD_LANCE: - dev_set_drvdata(bdev, dev); - - start = to_tc_dev(bdev)->resource.start; - len = to_tc_dev(bdev)->resource.end - start + 1; - if (!request_mem_region(start, len, bdev->bus_id)) { - printk(KERN_ERR - "%s: Unable to reserve MMIO resource\n", - bdev->bus_id); - ret = -EBUSY; - goto err_out_dev; - } + claim_tc_card(slot); - dev->mem_start = CKSEG1ADDR(start); + dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot)); dev->mem_end = dev->mem_start + 0x100000; dev->base_addr = dev->mem_start + 0x100000; - dev->irq = to_tc_dev(bdev)->interrupt; + dev->irq = get_tc_irq_nr(slot); esar_base = dev->mem_start + 0x1c0002; lp->dma_irq = -1; @@ -1192,7 +1174,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type) printk(KERN_ERR "%s: declance_init called with unknown type\n", name); ret = -ENODEV; - goto err_out_dev; + goto err_out_free_dev; } ll = (struct lance_regs *) dev->base_addr; @@ -1206,7 +1188,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type) "%s: Ethernet station address prom not found!\n", name); ret = -ENODEV; - goto err_out_resource; + goto err_out_free_dev; } /* Check the prom contents */ for (i = 0; i < 8; i++) { @@ -1216,7 +1198,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type) printk(KERN_ERR "%s: Something is wrong with the " "ethernet station address prom!\n", name); ret = -ENODEV; - goto err_out_resource; + goto err_out_free_dev; } } @@ -1273,51 +1255,48 @@ static int __init dec_lance_probe(struct device *bdev, const int type) if (ret) { printk(KERN_ERR "%s: Unable to register netdev, aborting.\n", name); - goto err_out_resource; + goto err_out_free_dev; } - if (!bdev) { - lp->next = root_lance_dev; - root_lance_dev = dev; - } + lp->next = root_lance_dev; + root_lance_dev = dev; printk("%s: registered as %s.\n", name, dev->name); return 0; -err_out_resource: - if (bdev) - release_mem_region(start, len); - -err_out_dev: +err_out_free_dev: free_netdev(dev); err_out: return ret; } -static void __exit dec_lance_remove(struct device *bdev) -{ - struct net_device *dev = dev_get_drvdata(bdev); - resource_size_t start, len; - - unregister_netdev(dev); - start = to_tc_dev(bdev)->resource.start; - len = to_tc_dev(bdev)->resource.end - start + 1; - release_mem_region(start, len); - free_netdev(dev); -} /* Find all the lance cards on the system and initialize them */ -static int __init dec_lance_platform_probe(void) +static int __init dec_lance_probe(void) { int count = 0; + /* Scan slots for PMAD-AA cards first. */ +#ifdef CONFIG_TC + if (TURBOCHANNEL) { + int slot; + + while ((slot = search_tc_card("PMAD-AA")) >= 0) { + if (dec_lance_init(PMAD_LANCE, slot) < 0) + break; + count++; + } + } +#endif + + /* Then handle onboard devices. */ if (dec_interrupt[DEC_IRQ_LANCE] >= 0) { if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) { - if (dec_lance_probe(NULL, ASIC_LANCE) >= 0) + if (dec_lance_init(ASIC_LANCE, -1) >= 0) count++; } else if (!TURBOCHANNEL) { - if (dec_lance_probe(NULL, PMAX_LANCE) >= 0) + if (dec_lance_init(PMAX_LANCE, -1) >= 0) count++; } } @@ -1325,70 +1304,21 @@ static int __init dec_lance_platform_probe(void) return (count > 0) ? 0 : -ENODEV; } -static void __exit dec_lance_platform_remove(void) +static void __exit dec_lance_cleanup(void) { while (root_lance_dev) { struct net_device *dev = root_lance_dev; struct lance_private *lp = netdev_priv(dev); unregister_netdev(dev); +#ifdef CONFIG_TC + if (lp->slot >= 0) + release_tc_card(lp->slot); +#endif root_lance_dev = lp->next; free_netdev(dev); } } -#ifdef CONFIG_TC -static int __init dec_lance_tc_probe(struct device *dev); -static int __exit dec_lance_tc_remove(struct device *dev); - -static const struct tc_device_id dec_lance_tc_table[] = { - { "DEC ", "PMAD-AA " }, - { } -}; -MODULE_DEVICE_TABLE(tc, dec_lance_tc_table); - -static struct tc_driver dec_lance_tc_driver = { - .id_table = dec_lance_tc_table, - .driver = { - .name = "declance", - .bus = &tc_bus_type, - .probe = dec_lance_tc_probe, - .remove = __exit_p(dec_lance_tc_remove), - }, -}; - -static int __init dec_lance_tc_probe(struct device *dev) -{ - int status = dec_lance_probe(dev, PMAD_LANCE); - if (!status) - get_device(dev); - return status; -} - -static int __exit dec_lance_tc_remove(struct device *dev) -{ - put_device(dev); - dec_lance_remove(dev); - return 0; -} -#endif - -static int __init dec_lance_init(void) -{ - int status; - - status = tc_register_driver(&dec_lance_tc_driver); - if (!status) - dec_lance_platform_probe(); - return status; -} - -static void __exit dec_lance_exit(void) -{ - dec_lance_platform_remove(); - tc_unregister_driver(&dec_lance_tc_driver); -} - - -module_init(dec_lance_init); -module_exit(dec_lance_exit); +module_init(dec_lance_probe); +module_exit(dec_lance_cleanup); diff --git a/trunk/drivers/net/e1000/e1000.h b/trunk/drivers/net/e1000/e1000.h index 689f158a469e..f091042b146e 100644 --- a/trunk/drivers/net/e1000/e1000.h +++ b/trunk/drivers/net/e1000/e1000.h @@ -59,13 +59,17 @@ #include #include #include +#ifdef NETIF_F_TSO6 #include +#endif #include #include #include #include #include +#ifdef NETIF_F_TSO #include +#endif #include #include #include @@ -253,6 +257,7 @@ struct e1000_adapter { spinlock_t tx_queue_lock; #endif atomic_t irq_sem; + unsigned int detect_link; unsigned int total_tx_bytes; unsigned int total_tx_packets; unsigned int total_rx_bytes; @@ -343,7 +348,9 @@ struct e1000_adapter { boolean_t have_msi; #endif /* to not mess up cache alignment, always add to the bottom */ +#ifdef NETIF_F_TSO boolean_t tso_force; +#endif boolean_t smart_power_down; /* phy smart power down */ boolean_t quad_port_a; unsigned long flags; diff --git a/trunk/drivers/net/e1000/e1000_ethtool.c b/trunk/drivers/net/e1000/e1000_ethtool.c index 44ebc72962dc..fb96c87f9e56 100644 --- a/trunk/drivers/net/e1000/e1000_ethtool.c +++ b/trunk/drivers/net/e1000/e1000_ethtool.c @@ -338,6 +338,7 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data) return 0; } +#ifdef NETIF_F_TSO static int e1000_set_tso(struct net_device *netdev, uint32_t data) { @@ -351,15 +352,18 @@ e1000_set_tso(struct net_device *netdev, uint32_t data) else netdev->features &= ~NETIF_F_TSO; +#ifdef NETIF_F_TSO6 if (data) netdev->features |= NETIF_F_TSO6; else netdev->features &= ~NETIF_F_TSO6; +#endif DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled"); adapter->tso_force = TRUE; return 0; } +#endif /* NETIF_F_TSO */ static uint32_t e1000_get_msglevel(struct net_device *netdev) @@ -1967,8 +1971,10 @@ static const struct ethtool_ops e1000_ethtool_ops = { .set_tx_csum = e1000_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO .get_tso = ethtool_op_get_tso, .set_tso = e1000_set_tso, +#endif .self_test_count = e1000_diag_test_count, .self_test = e1000_diag_test, .get_strings = e1000_get_strings, diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c index 619c89218b4b..c6259c7127f6 100644 --- a/trunk/drivers/net/e1000/e1000_main.c +++ b/trunk/drivers/net/e1000/e1000_main.c @@ -36,7 +36,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "7.3.20-k2"DRIVERNAPI +#define DRV_VERSION "7.3.15-k2"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; @@ -990,12 +990,16 @@ e1000_probe(struct pci_dev *pdev, netdev->features &= ~NETIF_F_HW_VLAN_FILTER; } +#ifdef NETIF_F_TSO if ((adapter->hw.mac_type >= e1000_82544) && (adapter->hw.mac_type != e1000_82547)) netdev->features |= NETIF_F_TSO; +#ifdef NETIF_F_TSO6 if (adapter->hw.mac_type > e1000_82547_rev_2) netdev->features |= NETIF_F_TSO6; +#endif +#endif if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; @@ -2579,22 +2583,15 @@ e1000_watchdog(unsigned long data) if (link) { if (!netif_carrier_ok(netdev)) { - uint32_t ctrl; boolean_t txb2b = 1; e1000_get_speed_and_duplex(&adapter->hw, &adapter->link_speed, &adapter->link_duplex); - ctrl = E1000_READ_REG(&adapter->hw, CTRL); - DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s, " - "Flow Control: %s\n", - adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "Full Duplex" : "Half Duplex", - ((ctrl & E1000_CTRL_TFCE) && (ctrl & - E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl & - E1000_CTRL_RFCE) ? "RX" : ((ctrl & - E1000_CTRL_TFCE) ? "TX" : "None" ))); + DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s\n", + adapter->link_speed, + adapter->link_duplex == FULL_DUPLEX ? + "Full Duplex" : "Half Duplex"); /* tweak tx_queue_len according to speed/duplex * and adjust the timeout factor */ @@ -2622,6 +2619,7 @@ e1000_watchdog(unsigned long data) E1000_WRITE_REG(&adapter->hw, TARC0, tarc0); } +#ifdef NETIF_F_TSO /* disable TSO for pcie and 10/100 speeds, to avoid * some hardware issues */ if (!adapter->tso_force && @@ -2632,17 +2630,22 @@ e1000_watchdog(unsigned long data) DPRINTK(PROBE,INFO, "10/100 speed: disabling TSO\n"); netdev->features &= ~NETIF_F_TSO; +#ifdef NETIF_F_TSO6 netdev->features &= ~NETIF_F_TSO6; +#endif break; case SPEED_1000: netdev->features |= NETIF_F_TSO; +#ifdef NETIF_F_TSO6 netdev->features |= NETIF_F_TSO6; +#endif break; default: /* oops */ break; } } +#endif /* enable transmits in the hardware, need to do this * after setting TARC0 */ @@ -2872,6 +2875,7 @@ static int e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, struct sk_buff *skb) { +#ifdef NETIF_F_TSO struct e1000_context_desc *context_desc; struct e1000_buffer *buffer_info; unsigned int i; @@ -2900,6 +2904,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, 0); cmd_length = E1000_TXD_CMD_IP; ipcse = skb->h.raw - skb->data - 1; +#ifdef NETIF_F_TSO6 } else if (skb->protocol == htons(ETH_P_IPV6)) { skb->nh.ipv6h->payload_len = 0; skb->h.th->check = @@ -2909,6 +2914,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, IPPROTO_TCP, 0); ipcse = 0; +#endif } ipcss = skb->nh.raw - skb->data; ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data; @@ -2941,6 +2947,8 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, return TRUE; } +#endif + return FALSE; } @@ -2960,9 +2968,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, buffer_info = &tx_ring->buffer_info[i]; context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - context_desc->lower_setup.ip_config = 0; context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = css + skb->csum; + context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset; context_desc->upper_setup.tcp_fields.tucse = 0; context_desc->tcp_seg_setup.data = 0; context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); @@ -2998,6 +3005,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, while (len) { buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); +#ifdef NETIF_F_TSO /* Workaround for Controller erratum -- * descriptor for non-tso packet in a linear SKB that follows a * tso gets written back prematurely before the data is fully @@ -3012,6 +3020,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, * in TSO mode. Append 4-byte sentinel desc */ if (unlikely(mss && !nr_frags && size == len && size > 8)) size -= 4; +#endif /* work-around for errata 10 and it applies * to all controllers in PCI-X mode * The fix is to make sure that the first descriptor of a @@ -3053,10 +3062,12 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, while (len) { buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); +#ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8)) size -= 4; +#endif /* Workaround for potential 82544 hang in PCI-X. * Avoid terminating buffers within evenly-aligned * dwords. */ @@ -3281,6 +3292,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (adapter->hw.mac_type >= e1000_82571) max_per_txd = 8192; +#ifdef NETIF_F_TSO mss = skb_shinfo(skb)->gso_size; /* The controller does a simple calculation to * make sure there is enough room in the FIFO before @@ -3334,10 +3346,16 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) count++; count++; +#else + if (skb->ip_summed == CHECKSUM_PARTIAL) + count++; +#endif +#ifdef NETIF_F_TSO /* Controller Erratum workaround */ if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb)) count++; +#endif count += TXD_USE_COUNT(len, max_txd_pwr); @@ -3584,7 +3602,7 @@ e1000_update_stats(struct e1000_adapter *adapter) */ if (adapter->link_speed == 0) return; - if (pci_channel_offline(pdev)) + if (pdev->error_state && pdev->error_state != pci_channel_io_normal) return; spin_lock_irqsave(&adapter->stats_lock, flags); @@ -3747,8 +3765,8 @@ e1000_update_stats(struct e1000_adapter *adapter) * @data: pointer to a network interface device structure **/ -static irqreturn_t -e1000_intr_msi(int irq, void *data) +static +irqreturn_t e1000_intr_msi(int irq, void *data) { struct net_device *netdev = data; struct e1000_adapter *adapter = netdev_priv(netdev); @@ -3756,27 +3774,49 @@ e1000_intr_msi(int irq, void *data) #ifndef CONFIG_E1000_NAPI int i; #endif - uint32_t icr = E1000_READ_REG(hw, ICR); + /* this code avoids the read of ICR but has to get 1000 interrupts + * at every link change event before it will notice the change */ + if (++adapter->detect_link >= 1000) { + uint32_t icr = E1000_READ_REG(hw, ICR); #ifdef CONFIG_E1000_NAPI - /* read ICR disables interrupts using IAM, so keep up with our - * enable/disable accounting */ - atomic_inc(&adapter->irq_sem); + /* read ICR disables interrupts using IAM, so keep up with our + * enable/disable accounting */ + atomic_inc(&adapter->irq_sem); #endif - if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { - hw->get_link_status = 1; - /* 80003ES2LAN workaround-- For packet buffer work-around on - * link down event; disable receives here in the ISR and reset - * adapter in watchdog */ - if (netif_carrier_ok(netdev) && - (adapter->hw.mac_type == e1000_80003es2lan)) { - /* disable receives */ - uint32_t rctl = E1000_READ_REG(hw, RCTL); - E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); + adapter->detect_link = 0; + if ((icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) && + (icr & E1000_ICR_INT_ASSERTED)) { + hw->get_link_status = 1; + /* 80003ES2LAN workaround-- + * For packet buffer work-around on link down event; + * disable receives here in the ISR and + * reset adapter in watchdog + */ + if (netif_carrier_ok(netdev) && + (adapter->hw.mac_type == e1000_80003es2lan)) { + /* disable receives */ + uint32_t rctl = E1000_READ_REG(hw, RCTL); + E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); + } + /* guard against interrupt when we're going down */ + if (!test_bit(__E1000_DOWN, &adapter->flags)) + mod_timer(&adapter->watchdog_timer, + jiffies + 1); } - /* guard against interrupt when we're going down */ - if (!test_bit(__E1000_DOWN, &adapter->flags)) - mod_timer(&adapter->watchdog_timer, jiffies + 1); + } else { + E1000_WRITE_REG(hw, ICR, (0xffffffff & ~(E1000_ICR_RXSEQ | + E1000_ICR_LSC))); + /* bummer we have to flush here, but things break otherwise as + * some event appears to be lost or delayed and throughput + * drops. In almost all tests this flush is un-necessary */ + E1000_WRITE_FLUSH(hw); +#ifdef CONFIG_E1000_NAPI + /* Interrupt Auto-Mask (IAM)...upon writing ICR, interrupts are + * masked. No need for the IMC write, but it does mean we + * should account for it ASAP. */ + atomic_inc(&adapter->irq_sem); +#endif } #ifdef CONFIG_E1000_NAPI @@ -3796,7 +3836,7 @@ e1000_intr_msi(int irq, void *data) for (i = 0; i < E1000_MAX_INTR; i++) if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & - e1000_clean_tx_irq(adapter, adapter->tx_ring))) + !e1000_clean_tx_irq(adapter, adapter->tx_ring))) break; if (likely(adapter->itr_setting & 3)) @@ -3899,7 +3939,7 @@ e1000_intr(int irq, void *data) for (i = 0; i < E1000_MAX_INTR; i++) if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & - e1000_clean_tx_irq(adapter, adapter->tx_ring))) + !e1000_clean_tx_irq(adapter, adapter->tx_ring))) break; if (likely(adapter->itr_setting & 3)) @@ -3949,7 +3989,7 @@ e1000_clean(struct net_device *poll_dev, int *budget) poll_dev->quota -= work_done; /* If no Tx and not enough Rx work done, exit the polling mode */ - if ((tx_cleaned && (work_done < work_to_do)) || + if ((!tx_cleaned && (work_done == 0)) || !netif_running(poll_dev)) { quit_polling: if (likely(adapter->itr_setting & 3)) @@ -3979,7 +4019,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, #ifdef CONFIG_E1000_NAPI unsigned int count = 0; #endif - boolean_t cleaned = TRUE; + boolean_t cleaned = FALSE; unsigned int total_tx_bytes=0, total_tx_packets=0; i = tx_ring->next_to_clean; @@ -3994,13 +4034,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, if (cleaned) { struct sk_buff *skb = buffer_info->skb; - unsigned int segs, bytecount; - segs = skb_shinfo(skb)->gso_segs ?: 1; - /* multiply data chunks by size of headers */ - bytecount = ((segs - 1) * skb_headlen(skb)) + - skb->len; + unsigned int segs = skb_shinfo(skb)->gso_segs; total_tx_packets += segs; - total_tx_bytes += bytecount; + total_tx_packets++; + total_tx_bytes += skb->len; } e1000_unmap_and_free_tx_resource(adapter, buffer_info); tx_desc->upper.data = 0; @@ -4013,10 +4050,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, #ifdef CONFIG_E1000_NAPI #define E1000_TX_WEIGHT 64 /* weight of a sort for tx, to avoid endless transmit cleanup */ - if (count++ == E1000_TX_WEIGHT) { - cleaned = FALSE; - break; - } + if (count++ == E1000_TX_WEIGHT) break; #endif } diff --git a/trunk/drivers/net/e1000/e1000_osdep.h b/trunk/drivers/net/e1000/e1000_osdep.h index 10af742d8a20..18afc0c25dac 100644 --- a/trunk/drivers/net/e1000/e1000_osdep.h +++ b/trunk/drivers/net/e1000/e1000_osdep.h @@ -48,6 +48,8 @@ typedef enum { TRUE = 1 } boolean_t; +#define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B) + #ifdef DBG #define DEBUGOUT(S) printk(KERN_DEBUG S "\n") #define DEBUGOUT1(S, A...) printk(KERN_DEBUG S "\n", A) @@ -56,7 +58,7 @@ typedef enum { #define DEBUGOUT1(S, A...) #endif -#define DEBUGFUNC(F) DEBUGOUT(F "\n") +#define DEBUGFUNC(F) DEBUGOUT(F) #define DEBUGOUT2 DEBUGOUT1 #define DEBUGOUT3 DEBUGOUT2 #define DEBUGOUT7 DEBUGOUT3 diff --git a/trunk/drivers/net/e1000/e1000_param.c b/trunk/drivers/net/e1000/e1000_param.c index f8862e203ac9..cf2a279307e1 100644 --- a/trunk/drivers/net/e1000/e1000_param.c +++ b/trunk/drivers/net/e1000/e1000_param.c @@ -760,13 +760,22 @@ e1000_check_copper_options(struct e1000_adapter *adapter) case SPEED_1000: DPRINTK(PROBE, INFO, "1000 Mbps Speed specified without " "Duplex\n"); - goto full_duplex_only; + DPRINTK(PROBE, INFO, + "Using Autonegotiation at 1000 Mbps " + "Full Duplex only\n"); + adapter->hw.autoneg = adapter->fc_autoneg = 1; + adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; + break; case SPEED_1000 + HALF_DUPLEX: DPRINTK(PROBE, INFO, "Half Duplex is not supported at 1000 Mbps\n"); - /* fall through */ + DPRINTK(PROBE, INFO, + "Using Autonegotiation at 1000 Mbps " + "Full Duplex only\n"); + adapter->hw.autoneg = adapter->fc_autoneg = 1; + adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; + break; case SPEED_1000 + FULL_DUPLEX: -full_duplex_only: DPRINTK(PROBE, INFO, "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); adapter->hw.autoneg = adapter->fc_autoneg = 1; diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c index a363148d0198..93f2b7a22160 100644 --- a/trunk/drivers/net/forcedeth.c +++ b/trunk/drivers/net/forcedeth.c @@ -111,7 +111,6 @@ * 0.57: 14 May 2006: Mac address set in probe/remove and order corrections. * 0.58: 30 Oct 2006: Added support for sideband management unit. * 0.59: 30 Oct 2006: Added support for recoverable error. - * 0.60: 20 Jan 2007: Code optimizations for rings, rx & tx data paths, and stats. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -128,7 +127,7 @@ #else #define DRIVERNAPI #endif -#define FORCEDETH_VERSION "0.60" +#define FORCEDETH_VERSION "0.59" #define DRV_NAME "forcedeth" #include @@ -174,10 +173,9 @@ #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ #define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */ #define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */ -#define DEV_HAS_STATISTICS_V1 0x0400 /* device supports hw statistics version 1 */ -#define DEV_HAS_STATISTICS_V2 0x0800 /* device supports hw statistics version 2 */ -#define DEV_HAS_TEST_EXTENDED 0x1000 /* device supports extended diagnostic test */ -#define DEV_HAS_MGMT_UNIT 0x2000 /* device supports management unit */ +#define DEV_HAS_STATISTICS 0x0400 /* device supports hw statistics */ +#define DEV_HAS_TEST_EXTENDED 0x0800 /* device supports extended diagnostic test */ +#define DEV_HAS_MGMT_UNIT 0x1000 /* device supports management unit */ enum { NvRegIrqStatus = 0x000, @@ -212,7 +210,7 @@ enum { * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms */ NvRegPollingInterval = 0x00c, -#define NVREG_POLL_DEFAULT_THROUGHPUT 970 /* backup tx cleanup if loop max reached */ +#define NVREG_POLL_DEFAULT_THROUGHPUT 970 #define NVREG_POLL_DEFAULT_CPU 13 NvRegMSIMap0 = 0x020, NvRegMSIMap1 = 0x024, @@ -306,8 +304,8 @@ enum { #define NVREG_TXRXCTL_RESET 0x0010 #define NVREG_TXRXCTL_RXCHECK 0x0400 #define NVREG_TXRXCTL_DESC_1 0 -#define NVREG_TXRXCTL_DESC_2 0x002100 -#define NVREG_TXRXCTL_DESC_3 0xc02200 +#define NVREG_TXRXCTL_DESC_2 0x02100 +#define NVREG_TXRXCTL_DESC_3 0x02200 #define NVREG_TXRXCTL_VLANSTRIP 0x00040 #define NVREG_TXRXCTL_VLANINS 0x00080 NvRegTxRingPhysAddrHigh = 0x148, @@ -489,8 +487,7 @@ union ring_type { /* Miscelaneous hardware related defines: */ #define NV_PCI_REGSZ_VER1 0x270 -#define NV_PCI_REGSZ_VER2 0x2d4 -#define NV_PCI_REGSZ_VER3 0x604 +#define NV_PCI_REGSZ_VER2 0x604 /* various timeout delays: all in usec */ #define NV_TXRX_RESET_DELAY 4 @@ -521,6 +518,12 @@ union ring_type { #define TX_RING_MIN 64 #define RING_MAX_DESC_VER_1 1024 #define RING_MAX_DESC_VER_2_3 16384 +/* + * Difference between the get and put pointers for the tx ring. + * This is used to throttle the amount of data outstanding in the + * tx ring. + */ +#define TX_LIMIT_DIFFERENCE 1 /* rx/tx mac addr + type + vlan + align + slack*/ #define NV_RX_HEADERS (64) @@ -608,6 +611,9 @@ static const struct nv_ethtool_str nv_estats_str[] = { { "tx_carrier_errors" }, { "tx_excess_deferral" }, { "tx_retry_error" }, + { "tx_deferral" }, + { "tx_packets" }, + { "tx_pause" }, { "rx_frame_error" }, { "rx_extra_byte" }, { "rx_late_collision" }, @@ -620,17 +626,11 @@ static const struct nv_ethtool_str nv_estats_str[] = { { "rx_unicast" }, { "rx_multicast" }, { "rx_broadcast" }, - { "rx_packets" }, - { "rx_errors_total" }, - { "tx_errors_total" }, - - /* version 2 stats */ - { "tx_deferral" }, - { "tx_packets" }, { "rx_bytes" }, - { "tx_pause" }, { "rx_pause" }, - { "rx_drop_frame" } + { "rx_drop_frame" }, + { "rx_packets" }, + { "rx_errors_total" } }; struct nv_ethtool_stats { @@ -643,6 +643,9 @@ struct nv_ethtool_stats { u64 tx_carrier_errors; u64 tx_excess_deferral; u64 tx_retry_error; + u64 tx_deferral; + u64 tx_packets; + u64 tx_pause; u64 rx_frame_error; u64 rx_extra_byte; u64 rx_late_collision; @@ -655,22 +658,13 @@ struct nv_ethtool_stats { u64 rx_unicast; u64 rx_multicast; u64 rx_broadcast; - u64 rx_packets; - u64 rx_errors_total; - u64 tx_errors_total; - - /* version 2 stats */ - u64 tx_deferral; - u64 tx_packets; u64 rx_bytes; - u64 tx_pause; u64 rx_pause; u64 rx_drop_frame; + u64 rx_packets; + u64 rx_errors_total; }; -#define NV_DEV_STATISTICS_V2_COUNT (sizeof(struct nv_ethtool_stats)/sizeof(u64)) -#define NV_DEV_STATISTICS_V1_COUNT (NV_DEV_STATISTICS_V2_COUNT - 6) - /* diagnostics */ #define NV_TEST_COUNT_BASE 3 #define NV_TEST_COUNT_EXTENDED 4 @@ -697,12 +691,6 @@ static const struct register_test nv_registers_test[] = { { 0,0 } }; -struct nv_skb_map { - struct sk_buff *skb; - dma_addr_t dma; - unsigned int dma_len; -}; - /* * SMP locking: * All hardware access under dev->priv->lock, except the performance @@ -753,12 +741,10 @@ struct fe_priv { /* rx specific fields. * Locking: Within irq hander or disable_irq+spin_lock(&np->lock); */ - union ring_type get_rx, put_rx, first_rx, last_rx; - struct nv_skb_map *get_rx_ctx, *put_rx_ctx; - struct nv_skb_map *first_rx_ctx, *last_rx_ctx; - struct nv_skb_map *rx_skb; - union ring_type rx_ring; + unsigned int cur_rx, refill_rx; + struct sk_buff **rx_skbuff; + dma_addr_t *rx_dma; unsigned int rx_buf_sz; unsigned int pkt_limit; struct timer_list oom_kick; @@ -775,15 +761,15 @@ struct fe_priv { /* * tx specific fields. */ - union ring_type get_tx, put_tx, first_tx, last_tx; - struct nv_skb_map *get_tx_ctx, *put_tx_ctx; - struct nv_skb_map *first_tx_ctx, *last_tx_ctx; - struct nv_skb_map *tx_skb; - union ring_type tx_ring; + unsigned int next_tx, nic_tx; + struct sk_buff **tx_skbuff; + dma_addr_t *tx_dma; + unsigned int *tx_dma_len; u32 tx_flags; int tx_ring_size; - int tx_stop; + int tx_limit_start; + int tx_limit_stop; /* vlan fields */ struct vlan_group *vlangrp; @@ -935,10 +921,16 @@ static void free_rings(struct net_device *dev) pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size), np->rx_ring.ex, np->ring_addr); } - if (np->rx_skb) - kfree(np->rx_skb); - if (np->tx_skb) - kfree(np->tx_skb); + if (np->rx_skbuff) + kfree(np->rx_skbuff); + if (np->rx_dma) + kfree(np->rx_dma); + if (np->tx_skbuff) + kfree(np->tx_skbuff); + if (np->tx_dma) + kfree(np->tx_dma); + if (np->tx_dma_len) + kfree(np->tx_dma_len); } static int using_multi_irqs(struct net_device *dev) @@ -1287,61 +1279,6 @@ static void nv_mac_reset(struct net_device *dev) pci_push(base); } -static void nv_get_hw_stats(struct net_device *dev) -{ - struct fe_priv *np = netdev_priv(dev); - u8 __iomem *base = get_hwbase(dev); - - np->estats.tx_bytes += readl(base + NvRegTxCnt); - np->estats.tx_zero_rexmt += readl(base + NvRegTxZeroReXmt); - np->estats.tx_one_rexmt += readl(base + NvRegTxOneReXmt); - np->estats.tx_many_rexmt += readl(base + NvRegTxManyReXmt); - np->estats.tx_late_collision += readl(base + NvRegTxLateCol); - np->estats.tx_fifo_errors += readl(base + NvRegTxUnderflow); - np->estats.tx_carrier_errors += readl(base + NvRegTxLossCarrier); - np->estats.tx_excess_deferral += readl(base + NvRegTxExcessDef); - np->estats.tx_retry_error += readl(base + NvRegTxRetryErr); - np->estats.rx_frame_error += readl(base + NvRegRxFrameErr); - np->estats.rx_extra_byte += readl(base + NvRegRxExtraByte); - np->estats.rx_late_collision += readl(base + NvRegRxLateCol); - np->estats.rx_runt += readl(base + NvRegRxRunt); - np->estats.rx_frame_too_long += readl(base + NvRegRxFrameTooLong); - np->estats.rx_over_errors += readl(base + NvRegRxOverflow); - np->estats.rx_crc_errors += readl(base + NvRegRxFCSErr); - np->estats.rx_frame_align_error += readl(base + NvRegRxFrameAlignErr); - np->estats.rx_length_error += readl(base + NvRegRxLenErr); - np->estats.rx_unicast += readl(base + NvRegRxUnicast); - np->estats.rx_multicast += readl(base + NvRegRxMulticast); - np->estats.rx_broadcast += readl(base + NvRegRxBroadcast); - np->estats.rx_packets = - np->estats.rx_unicast + - np->estats.rx_multicast + - np->estats.rx_broadcast; - np->estats.rx_errors_total = - np->estats.rx_crc_errors + - np->estats.rx_over_errors + - np->estats.rx_frame_error + - (np->estats.rx_frame_align_error - np->estats.rx_extra_byte) + - np->estats.rx_late_collision + - np->estats.rx_runt + - np->estats.rx_frame_too_long; - np->estats.tx_errors_total = - np->estats.tx_late_collision + - np->estats.tx_fifo_errors + - np->estats.tx_carrier_errors + - np->estats.tx_excess_deferral + - np->estats.tx_retry_error; - - if (np->driver_data & DEV_HAS_STATISTICS_V2) { - np->estats.tx_deferral += readl(base + NvRegTxDef); - np->estats.tx_packets += readl(base + NvRegTxFrame); - np->estats.rx_bytes += readl(base + NvRegRxCnt); - np->estats.tx_pause += readl(base + NvRegTxPause); - np->estats.rx_pause += readl(base + NvRegRxPause); - np->estats.rx_drop_frame += readl(base + NvRegRxDropFrame); - } -} - /* * nv_get_stats: dev->get_stats function * Get latest stats value from the nic. @@ -1352,19 +1289,10 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); - /* If the nic supports hw counters then retrieve latest values */ - if (np->driver_data & (DEV_HAS_STATISTICS_V1|DEV_HAS_STATISTICS_V2)) { - nv_get_hw_stats(dev); - - /* copy to net_device stats */ - np->stats.tx_bytes = np->estats.tx_bytes; - np->stats.tx_fifo_errors = np->estats.tx_fifo_errors; - np->stats.tx_carrier_errors = np->estats.tx_carrier_errors; - np->stats.rx_crc_errors = np->estats.rx_crc_errors; - np->stats.rx_over_errors = np->estats.rx_over_errors; - np->stats.rx_errors = np->estats.rx_errors_total; - np->stats.tx_errors = np->estats.tx_errors_total; - } + /* It seems that the nic always generates interrupts and doesn't + * accumulate errors internally. Thus the current values in np->stats + * are already up to date. + */ return &np->stats; } @@ -1376,63 +1304,43 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev) static int nv_alloc_rx(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); - struct ring_desc* less_rx; + unsigned int refill_rx = np->refill_rx; + int nr; - less_rx = np->get_rx.orig; - if (less_rx-- == np->first_rx.orig) - less_rx = np->last_rx.orig; - - while (np->put_rx.orig != less_rx) { - struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD); - if (skb) { - skb->dev = dev; - np->put_rx_ctx->skb = skb; - np->put_rx_ctx->dma = pci_map_single(np->pci_dev, skb->data, - skb->end-skb->data, PCI_DMA_FROMDEVICE); - np->put_rx_ctx->dma_len = skb->end-skb->data; - np->put_rx.orig->buf = cpu_to_le32(np->put_rx_ctx->dma); - wmb(); - np->put_rx.orig->flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL); - if (unlikely(np->put_rx.orig++ == np->last_rx.orig)) - np->put_rx.orig = np->first_rx.orig; - if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx)) - np->put_rx_ctx = np->first_rx_ctx; - } else { - return 1; - } - } - return 0; -} + while (np->cur_rx != refill_rx) { + struct sk_buff *skb; -static int nv_alloc_rx_optimized(struct net_device *dev) -{ - struct fe_priv *np = netdev_priv(dev); - struct ring_desc_ex* less_rx; + nr = refill_rx % np->rx_ring_size; + if (np->rx_skbuff[nr] == NULL) { - less_rx = np->get_rx.ex; - if (less_rx-- == np->first_rx.ex) - less_rx = np->last_rx.ex; + skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD); + if (!skb) + break; - while (np->put_rx.ex != less_rx) { - struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD); - if (skb) { skb->dev = dev; - np->put_rx_ctx->skb = skb; - np->put_rx_ctx->dma = pci_map_single(np->pci_dev, skb->data, - skb->end-skb->data, PCI_DMA_FROMDEVICE); - np->put_rx_ctx->dma_len = skb->end-skb->data; - np->put_rx.ex->bufhigh = cpu_to_le64(np->put_rx_ctx->dma) >> 32; - np->put_rx.ex->buflow = cpu_to_le64(np->put_rx_ctx->dma) & 0x0FFFFFFFF; + np->rx_skbuff[nr] = skb; + } else { + skb = np->rx_skbuff[nr]; + } + np->rx_dma[nr] = pci_map_single(np->pci_dev, skb->data, + skb->end-skb->data, PCI_DMA_FROMDEVICE); + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + np->rx_ring.orig[nr].buf = cpu_to_le32(np->rx_dma[nr]); wmb(); - np->put_rx.ex->flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL); - if (unlikely(np->put_rx.ex++ == np->last_rx.ex)) - np->put_rx.ex = np->first_rx.ex; - if (unlikely(np->put_rx_ctx++ == np->last_rx_ctx)) - np->put_rx_ctx = np->first_rx_ctx; + np->rx_ring.orig[nr].flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL); } else { - return 1; + np->rx_ring.ex[nr].bufhigh = cpu_to_le64(np->rx_dma[nr]) >> 32; + np->rx_ring.ex[nr].buflow = cpu_to_le64(np->rx_dma[nr]) & 0x0FFFFFFFF; + wmb(); + np->rx_ring.ex[nr].flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL); } + dprintk(KERN_DEBUG "%s: nv_alloc_rx: Packet %d marked as Available\n", + dev->name, refill_rx); + refill_rx++; } + np->refill_rx = refill_rx; + if (np->cur_rx - refill_rx == np->rx_ring_size) + return 1; return 0; } @@ -1450,7 +1358,6 @@ static void nv_do_rx_refill(unsigned long data) { struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); - int retcode; if (!using_multi_irqs(dev)) { if (np->msi_flags & NV_MSI_X_ENABLED) @@ -1460,11 +1367,7 @@ static void nv_do_rx_refill(unsigned long data) } else { disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); } - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - retcode = nv_alloc_rx(dev); - else - retcode = nv_alloc_rx_optimized(dev); - if (retcode) { + if (nv_alloc_rx(dev)) { spin_lock_irq(&np->lock); if (!np->in_shutdown) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); @@ -1485,81 +1388,56 @@ static void nv_init_rx(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); int i; - np->get_rx = np->put_rx = np->first_rx = np->rx_ring; - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - np->last_rx.orig = &np->rx_ring.orig[np->rx_ring_size-1]; - else - np->last_rx.ex = &np->rx_ring.ex[np->rx_ring_size-1]; - np->get_rx_ctx = np->put_rx_ctx = np->first_rx_ctx = np->rx_skb; - np->last_rx_ctx = &np->rx_skb[np->rx_ring_size-1]; - for (i = 0; i < np->rx_ring_size; i++) { - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + np->cur_rx = np->rx_ring_size; + np->refill_rx = 0; + for (i = 0; i < np->rx_ring_size; i++) + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) np->rx_ring.orig[i].flaglen = 0; - np->rx_ring.orig[i].buf = 0; - } else { + else np->rx_ring.ex[i].flaglen = 0; - np->rx_ring.ex[i].txvlan = 0; - np->rx_ring.ex[i].bufhigh = 0; - np->rx_ring.ex[i].buflow = 0; - } - np->rx_skb[i].skb = NULL; - np->rx_skb[i].dma = 0; - } } static void nv_init_tx(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); int i; - np->get_tx = np->put_tx = np->first_tx = np->tx_ring; - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - np->last_tx.orig = &np->tx_ring.orig[np->tx_ring_size-1]; - else - np->last_tx.ex = &np->tx_ring.ex[np->tx_ring_size-1]; - np->get_tx_ctx = np->put_tx_ctx = np->first_tx_ctx = np->tx_skb; - np->last_tx_ctx = &np->tx_skb[np->tx_ring_size-1]; + np->next_tx = np->nic_tx = 0; for (i = 0; i < np->tx_ring_size; i++) { - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) np->tx_ring.orig[i].flaglen = 0; - np->tx_ring.orig[i].buf = 0; - } else { + else np->tx_ring.ex[i].flaglen = 0; - np->tx_ring.ex[i].txvlan = 0; - np->tx_ring.ex[i].bufhigh = 0; - np->tx_ring.ex[i].buflow = 0; - } - np->tx_skb[i].skb = NULL; - np->tx_skb[i].dma = 0; + np->tx_skbuff[i] = NULL; + np->tx_dma[i] = 0; } } static int nv_init_ring(struct net_device *dev) { - struct fe_priv *np = netdev_priv(dev); - nv_init_tx(dev); nv_init_rx(dev); - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - return nv_alloc_rx(dev); - else - return nv_alloc_rx_optimized(dev); + return nv_alloc_rx(dev); } -static int nv_release_txskb(struct net_device *dev, struct nv_skb_map* tx_skb) +static int nv_release_txskb(struct net_device *dev, unsigned int skbnr) { struct fe_priv *np = netdev_priv(dev); - if (tx_skb->dma) { - pci_unmap_page(np->pci_dev, tx_skb->dma, - tx_skb->dma_len, + dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d\n", + dev->name, skbnr); + + if (np->tx_dma[skbnr]) { + pci_unmap_page(np->pci_dev, np->tx_dma[skbnr], + np->tx_dma_len[skbnr], PCI_DMA_TODEVICE); - tx_skb->dma = 0; + np->tx_dma[skbnr] = 0; } - if (tx_skb->skb) { - dev_kfree_skb_any(tx_skb->skb); - tx_skb->skb = NULL; + + if (np->tx_skbuff[skbnr]) { + dev_kfree_skb_any(np->tx_skbuff[skbnr]); + np->tx_skbuff[skbnr] = NULL; return 1; } else { return 0; @@ -1572,16 +1450,11 @@ static void nv_drain_tx(struct net_device *dev) unsigned int i; for (i = 0; i < np->tx_ring_size; i++) { - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) np->tx_ring.orig[i].flaglen = 0; - np->tx_ring.orig[i].buf = 0; - } else { + else np->tx_ring.ex[i].flaglen = 0; - np->tx_ring.ex[i].txvlan = 0; - np->tx_ring.ex[i].bufhigh = 0; - np->tx_ring.ex[i].buflow = 0; - } - if (nv_release_txskb(dev, &np->tx_skb[i])) + if (nv_release_txskb(dev, i)) np->stats.tx_dropped++; } } @@ -1590,24 +1463,18 @@ static void nv_drain_rx(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); int i; - for (i = 0; i < np->rx_ring_size; i++) { - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) np->rx_ring.orig[i].flaglen = 0; - np->rx_ring.orig[i].buf = 0; - } else { + else np->rx_ring.ex[i].flaglen = 0; - np->rx_ring.ex[i].txvlan = 0; - np->rx_ring.ex[i].bufhigh = 0; - np->rx_ring.ex[i].buflow = 0; - } wmb(); - if (np->rx_skb[i].skb) { - pci_unmap_single(np->pci_dev, np->rx_skb[i].dma, - np->rx_skb[i].skb->end-np->rx_skb[i].skb->data, + if (np->rx_skbuff[i]) { + pci_unmap_single(np->pci_dev, np->rx_dma[i], + np->rx_skbuff[i]->end-np->rx_skbuff[i]->data, PCI_DMA_FROMDEVICE); - dev_kfree_skb(np->rx_skb[i].skb); - np->rx_skb[i].skb = NULL; + dev_kfree_skb(np->rx_skbuff[i]); + np->rx_skbuff[i] = NULL; } } } @@ -1618,11 +1485,6 @@ static void drain_ring(struct net_device *dev) nv_drain_rx(dev); } -static inline u32 nv_get_empty_tx_slots(struct fe_priv *np) -{ - return (u32)(np->tx_ring_size - ((np->tx_ring_size + (np->put_tx_ctx - np->get_tx_ctx)) % np->tx_ring_size)); -} - /* * nv_start_xmit: dev->hard_start_xmit function * Called with netif_tx_lock held. @@ -1633,16 +1495,14 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 tx_flags = 0; u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET); unsigned int fragments = skb_shinfo(skb)->nr_frags; + unsigned int nr = (np->next_tx - 1) % np->tx_ring_size; + unsigned int start_nr = np->next_tx % np->tx_ring_size; unsigned int i; u32 offset = 0; u32 bcnt; u32 size = skb->len-skb->data_len; u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); - u32 empty_slots; - struct ring_desc* put_tx; - struct ring_desc* start_tx; - struct ring_desc* prev_tx; - struct nv_skb_map* prev_tx_ctx; + u32 tx_flags_vlan = 0; /* add fragments to entries count */ for (i = 0; i < fragments; i++) { @@ -1650,152 +1510,34 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); } - empty_slots = nv_get_empty_tx_slots(np); - if (unlikely(empty_slots <= entries)) { - spin_lock_irq(&np->lock); - netif_stop_queue(dev); - np->tx_stop = 1; - spin_unlock_irq(&np->lock); - return NETDEV_TX_BUSY; - } - - start_tx = put_tx = np->put_tx.orig; - - /* setup the header buffer */ - do { - prev_tx = put_tx; - prev_tx_ctx = np->put_tx_ctx; - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt, - PCI_DMA_TODEVICE); - np->put_tx_ctx->dma_len = bcnt; - put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma); - put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags); - - tx_flags = np->tx_flags; - offset += bcnt; - size -= bcnt; - if (unlikely(put_tx++ == np->last_tx.orig)) - put_tx = np->first_tx.orig; - if (unlikely(np->put_tx_ctx++ == np->last_tx_ctx)) - np->put_tx_ctx = np->first_tx_ctx; - } while (size); - - /* setup the fragments */ - for (i = 0; i < fragments; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - u32 size = frag->size; - offset = 0; - - do { - prev_tx = put_tx; - prev_tx_ctx = np->put_tx_ctx; - bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt, - PCI_DMA_TODEVICE); - np->put_tx_ctx->dma_len = bcnt; - put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma); - put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags); - - offset += bcnt; - size -= bcnt; - if (unlikely(put_tx++ == np->last_tx.orig)) - put_tx = np->first_tx.orig; - if (unlikely(np->put_tx_ctx++ == np->last_tx_ctx)) - np->put_tx_ctx = np->first_tx_ctx; - } while (size); - } - - /* set last fragment flag */ - prev_tx->flaglen |= cpu_to_le32(tx_flags_extra); - - /* save skb in this slot's context area */ - prev_tx_ctx->skb = skb; - - if (skb_is_gso(skb)) - tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT); - else - tx_flags_extra = skb->ip_summed == CHECKSUM_PARTIAL ? - NV_TX2_CHECKSUM_L3 | NV_TX2_CHECKSUM_L4 : 0; - spin_lock_irq(&np->lock); - /* set tx flags */ - start_tx->flaglen |= cpu_to_le32(tx_flags | tx_flags_extra); - np->put_tx.orig = put_tx; - - spin_unlock_irq(&np->lock); - - dprintk(KERN_DEBUG "%s: nv_start_xmit: entries %d queued for transmission. tx_flags_extra: %x\n", - dev->name, entries, tx_flags_extra); - { - int j; - for (j=0; j<64; j++) { - if ((j%16) == 0) - dprintk("\n%03x:", j); - dprintk(" %02x", ((unsigned char*)skb->data)[j]); - } - dprintk("\n"); - } - - dev->trans_start = jiffies; - writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); - return NETDEV_TX_OK; -} - -static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev) -{ - struct fe_priv *np = netdev_priv(dev); - u32 tx_flags = 0; - u32 tx_flags_extra; - unsigned int fragments = skb_shinfo(skb)->nr_frags; - unsigned int i; - u32 offset = 0; - u32 bcnt; - u32 size = skb->len-skb->data_len; - u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); - u32 empty_slots; - struct ring_desc_ex* put_tx; - struct ring_desc_ex* start_tx; - struct ring_desc_ex* prev_tx; - struct nv_skb_map* prev_tx_ctx; - - /* add fragments to entries count */ - for (i = 0; i < fragments; i++) { - entries += (skb_shinfo(skb)->frags[i].size >> NV_TX2_TSO_MAX_SHIFT) + - ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); - } - - empty_slots = nv_get_empty_tx_slots(np); - if (unlikely(empty_slots <= entries)) { - spin_lock_irq(&np->lock); - netif_stop_queue(dev); - np->tx_stop = 1; + if ((np->next_tx - np->nic_tx + entries - 1) > np->tx_limit_stop) { spin_unlock_irq(&np->lock); + netif_stop_queue(dev); return NETDEV_TX_BUSY; } - start_tx = put_tx = np->put_tx.ex; - /* setup the header buffer */ do { - prev_tx = put_tx; - prev_tx_ctx = np->put_tx_ctx; bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt, + nr = (nr + 1) % np->tx_ring_size; + + np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data + offset, bcnt, PCI_DMA_TODEVICE); - np->put_tx_ctx->dma_len = bcnt; - put_tx->bufhigh = cpu_to_le64(np->put_tx_ctx->dma) >> 32; - put_tx->buflow = cpu_to_le64(np->put_tx_ctx->dma) & 0x0FFFFFFFF; - put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags); + np->tx_dma_len[nr] = bcnt; - tx_flags = NV_TX2_VALID; + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + np->tx_ring.orig[nr].buf = cpu_to_le32(np->tx_dma[nr]); + np->tx_ring.orig[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags); + } else { + np->tx_ring.ex[nr].bufhigh = cpu_to_le64(np->tx_dma[nr]) >> 32; + np->tx_ring.ex[nr].buflow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF; + np->tx_ring.ex[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags); + } + tx_flags = np->tx_flags; offset += bcnt; size -= bcnt; - if (unlikely(put_tx++ == np->last_tx.ex)) - put_tx = np->first_tx.ex; - if (unlikely(np->put_tx_ctx++ == np->last_tx_ctx)) - np->put_tx_ctx = np->first_tx_ctx; } while (size); /* setup the fragments */ @@ -1805,57 +1547,58 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev) offset = 0; do { - prev_tx = put_tx; - prev_tx_ctx = np->put_tx_ctx; bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt, - PCI_DMA_TODEVICE); - np->put_tx_ctx->dma_len = bcnt; - put_tx->bufhigh = cpu_to_le64(np->put_tx_ctx->dma) >> 32; - put_tx->buflow = cpu_to_le64(np->put_tx_ctx->dma) & 0x0FFFFFFFF; - put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags); + nr = (nr + 1) % np->tx_ring_size; + np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt, + PCI_DMA_TODEVICE); + np->tx_dma_len[nr] = bcnt; + + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + np->tx_ring.orig[nr].buf = cpu_to_le32(np->tx_dma[nr]); + np->tx_ring.orig[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags); + } else { + np->tx_ring.ex[nr].bufhigh = cpu_to_le64(np->tx_dma[nr]) >> 32; + np->tx_ring.ex[nr].buflow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF; + np->tx_ring.ex[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags); + } offset += bcnt; size -= bcnt; - if (unlikely(put_tx++ == np->last_tx.ex)) - put_tx = np->first_tx.ex; - if (unlikely(np->put_tx_ctx++ == np->last_tx_ctx)) - np->put_tx_ctx = np->first_tx_ctx; } while (size); } /* set last fragment flag */ - prev_tx->flaglen |= cpu_to_le32(NV_TX2_LASTPACKET); + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + np->tx_ring.orig[nr].flaglen |= cpu_to_le32(tx_flags_extra); + } else { + np->tx_ring.ex[nr].flaglen |= cpu_to_le32(tx_flags_extra); + } - /* save skb in this slot's context area */ - prev_tx_ctx->skb = skb; + np->tx_skbuff[nr] = skb; +#ifdef NETIF_F_TSO if (skb_is_gso(skb)) tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT); else - tx_flags_extra = skb->ip_summed == CHECKSUM_PARTIAL ? +#endif + tx_flags_extra = skb->ip_summed == CHECKSUM_PARTIAL ? NV_TX2_CHECKSUM_L3 | NV_TX2_CHECKSUM_L4 : 0; /* vlan tag */ - if (likely(!np->vlangrp)) { - start_tx->txvlan = 0; - } else { - if (vlan_tx_tag_present(skb)) - start_tx->txvlan = cpu_to_le32(NV_TX3_VLAN_TAG_PRESENT | vlan_tx_tag_get(skb)); - else - start_tx->txvlan = 0; + if (np->vlangrp && vlan_tx_tag_present(skb)) { + tx_flags_vlan = NV_TX3_VLAN_TAG_PRESENT | vlan_tx_tag_get(skb); } - spin_lock_irq(&np->lock); - /* set tx flags */ - start_tx->flaglen |= cpu_to_le32(tx_flags | tx_flags_extra); - np->put_tx.ex = put_tx; - - spin_unlock_irq(&np->lock); + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + np->tx_ring.orig[start_nr].flaglen |= cpu_to_le32(tx_flags | tx_flags_extra); + } else { + np->tx_ring.ex[start_nr].txvlan = cpu_to_le32(tx_flags_vlan); + np->tx_ring.ex[start_nr].flaglen |= cpu_to_le32(tx_flags | tx_flags_extra); + } - dprintk(KERN_DEBUG "%s: nv_start_xmit_optimized: entries %d queued for transmission. tx_flags_extra: %x\n", - dev->name, entries, tx_flags_extra); + dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n", + dev->name, np->next_tx, entries, tx_flags_extra); { int j; for (j=0; j<64; j++) { @@ -1866,8 +1609,12 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev) dprintk("\n"); } + np->next_tx += entries; + dev->trans_start = jiffies; + spin_unlock_irq(&np->lock); writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); + pci_push(get_hwbase(dev)); return NETDEV_TX_OK; } @@ -1880,22 +1627,26 @@ static void nv_tx_done(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); u32 flags; - struct ring_desc* orig_get_tx = np->get_tx.orig; - - while ((np->get_tx.orig != np->put_tx.orig) && - !((flags = le32_to_cpu(np->get_tx.orig->flaglen)) & NV_TX_VALID)) { + unsigned int i; + struct sk_buff *skb; - dprintk(KERN_DEBUG "%s: nv_tx_done: flags 0x%x.\n", - dev->name, flags); + while (np->nic_tx != np->next_tx) { + i = np->nic_tx % np->tx_ring_size; - pci_unmap_page(np->pci_dev, np->get_tx_ctx->dma, - np->get_tx_ctx->dma_len, - PCI_DMA_TODEVICE); - np->get_tx_ctx->dma = 0; + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) + flags = le32_to_cpu(np->tx_ring.orig[i].flaglen); + else + flags = le32_to_cpu(np->tx_ring.ex[i].flaglen); + dprintk(KERN_DEBUG "%s: nv_tx_done: looking at packet %d, flags 0x%x.\n", + dev->name, np->nic_tx, flags); + if (flags & NV_TX_VALID) + break; if (np->desc_ver == DESC_VER_1) { if (flags & NV_TX_LASTPACKET) { - if (flags & NV_TX_ERROR) { + skb = np->tx_skbuff[i]; + if (flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION| + NV_TX_UNDERFLOW|NV_TX_ERROR)) { if (flags & NV_TX_UNDERFLOW) np->stats.tx_fifo_errors++; if (flags & NV_TX_CARRIERLOST) @@ -1903,14 +1654,14 @@ static void nv_tx_done(struct net_device *dev) np->stats.tx_errors++; } else { np->stats.tx_packets++; - np->stats.tx_bytes += np->get_tx_ctx->skb->len; + np->stats.tx_bytes += skb->len; } - dev_kfree_skb_any(np->get_tx_ctx->skb); - np->get_tx_ctx->skb = NULL; } } else { if (flags & NV_TX2_LASTPACKET) { - if (flags & NV_TX2_ERROR) { + skb = np->tx_skbuff[i]; + if (flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION| + NV_TX2_UNDERFLOW|NV_TX2_ERROR)) { if (flags & NV_TX2_UNDERFLOW) np->stats.tx_fifo_errors++; if (flags & NV_TX2_CARRIERLOST) @@ -1918,56 +1669,15 @@ static void nv_tx_done(struct net_device *dev) np->stats.tx_errors++; } else { np->stats.tx_packets++; - np->stats.tx_bytes += np->get_tx_ctx->skb->len; + np->stats.tx_bytes += skb->len; } - dev_kfree_skb_any(np->get_tx_ctx->skb); - np->get_tx_ctx->skb = NULL; } } - if (unlikely(np->get_tx.orig++ == np->last_tx.orig)) - np->get_tx.orig = np->first_tx.orig; - if (unlikely(np->get_tx_ctx++ == np->last_tx_ctx)) - np->get_tx_ctx = np->first_tx_ctx; + nv_release_txskb(dev, i); + np->nic_tx++; } - if (unlikely((np->tx_stop == 1) && (np->get_tx.orig != orig_get_tx))) { - np->tx_stop = 0; + if (np->next_tx - np->nic_tx < np->tx_limit_start) netif_wake_queue(dev); - } -} - -static void nv_tx_done_optimized(struct net_device *dev, int limit) -{ - struct fe_priv *np = netdev_priv(dev); - u32 flags; - struct ring_desc_ex* orig_get_tx = np->get_tx.ex; - - while ((np->get_tx.ex != np->put_tx.ex) && - !((flags = le32_to_cpu(np->get_tx.ex->flaglen)) & NV_TX_VALID) && - (limit-- > 0)) { - - dprintk(KERN_DEBUG "%s: nv_tx_done_optimized: flags 0x%x.\n", - dev->name, flags); - - pci_unmap_page(np->pci_dev, np->get_tx_ctx->dma, - np->get_tx_ctx->dma_len, - PCI_DMA_TODEVICE); - np->get_tx_ctx->dma = 0; - - if (flags & NV_TX2_LASTPACKET) { - if (!(flags & NV_TX2_ERROR)) - np->stats.tx_packets++; - dev_kfree_skb_any(np->get_tx_ctx->skb); - np->get_tx_ctx->skb = NULL; - } - if (unlikely(np->get_tx.ex++ == np->last_tx.ex)) - np->get_tx.ex = np->first_tx.ex; - if (unlikely(np->get_tx_ctx++ == np->last_tx_ctx)) - np->get_tx_ctx = np->first_tx_ctx; - } - if (unlikely((np->tx_stop == 1) && (np->get_tx.ex != orig_get_tx))) { - np->tx_stop = 0; - netif_wake_queue(dev); - } } /* @@ -1990,8 +1700,9 @@ static void nv_tx_timeout(struct net_device *dev) { int i; - printk(KERN_INFO "%s: Ring at %lx\n", - dev->name, (unsigned long)np->ring_addr); + printk(KERN_INFO "%s: Ring at %lx: next %d nic %d\n", + dev->name, (unsigned long)np->ring_addr, + np->next_tx, np->nic_tx); printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); for (i=0;i<=np->register_size;i+= 32) { printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", @@ -2039,16 +1750,13 @@ static void nv_tx_timeout(struct net_device *dev) nv_stop_tx(dev); /* 2) check that the packets were not sent already: */ - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - nv_tx_done(dev); - else - nv_tx_done_optimized(dev, np->tx_ring_size); + nv_tx_done(dev); /* 3) if there are dead entries: clear everything */ - if (np->get_tx_ctx != np->put_tx_ctx) { + if (np->next_tx != np->nic_tx) { printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name); nv_drain_tx(dev); - nv_init_tx(dev); + np->next_tx = np->nic_tx = 0; setup_hw_rings(dev, NV_SETUP_TX_RING); netif_wake_queue(dev); } @@ -2096,184 +1804,59 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen) */ dprintk(KERN_DEBUG "%s: nv_getlen: discarding long packet.\n", dev->name); - return -1; - } - } else { - /* short packet. Accept only if 802 values are also short */ - if (protolen > ETH_ZLEN) { - dprintk(KERN_DEBUG "%s: nv_getlen: discarding short packet.\n", - dev->name); - return -1; - } - dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n", - dev->name, datalen); - return datalen; - } -} - -static int nv_rx_process(struct net_device *dev, int limit) -{ - struct fe_priv *np = netdev_priv(dev); - u32 flags; - u32 rx_processed_cnt = 0; - struct sk_buff *skb; - int len; - - while((np->get_rx.orig != np->put_rx.orig) && - !((flags = le32_to_cpu(np->get_rx.orig->flaglen)) & NV_RX_AVAIL) && - (rx_processed_cnt++ < limit)) { - - dprintk(KERN_DEBUG "%s: nv_rx_process: flags 0x%x.\n", - dev->name, flags); - - /* - * the packet is for us - immediately tear down the pci mapping. - * TODO: check if a prefetch of the first cacheline improves - * the performance. - */ - pci_unmap_single(np->pci_dev, np->get_rx_ctx->dma, - np->get_rx_ctx->dma_len, - PCI_DMA_FROMDEVICE); - skb = np->get_rx_ctx->skb; - np->get_rx_ctx->skb = NULL; - - { - int j; - dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",flags); - for (j=0; j<64; j++) { - if ((j%16) == 0) - dprintk("\n%03x:", j); - dprintk(" %02x", ((unsigned char*)skb->data)[j]); - } - dprintk("\n"); - } - /* look at what we actually got: */ - if (np->desc_ver == DESC_VER_1) { - if (likely(flags & NV_RX_DESCRIPTORVALID)) { - len = flags & LEN_MASK_V1; - if (unlikely(flags & NV_RX_ERROR)) { - if (flags & NV_RX_ERROR4) { - len = nv_getlen(dev, skb->data, len); - if (len < 0) { - np->stats.rx_errors++; - dev_kfree_skb(skb); - goto next_pkt; - } - } - /* framing errors are soft errors */ - else if (flags & NV_RX_FRAMINGERR) { - if (flags & NV_RX_SUBSTRACT1) { - len--; - } - } - /* the rest are hard errors */ - else { - if (flags & NV_RX_MISSEDFRAME) - np->stats.rx_missed_errors++; - if (flags & NV_RX_CRCERR) - np->stats.rx_crc_errors++; - if (flags & NV_RX_OVERFLOW) - np->stats.rx_over_errors++; - np->stats.rx_errors++; - dev_kfree_skb(skb); - goto next_pkt; - } - } - } else { - dev_kfree_skb(skb); - goto next_pkt; - } - } else { - if (likely(flags & NV_RX2_DESCRIPTORVALID)) { - len = flags & LEN_MASK_V2; - if (unlikely(flags & NV_RX2_ERROR)) { - if (flags & NV_RX2_ERROR4) { - len = nv_getlen(dev, skb->data, len); - if (len < 0) { - np->stats.rx_errors++; - dev_kfree_skb(skb); - goto next_pkt; - } - } - /* framing errors are soft errors */ - else if (flags & NV_RX2_FRAMINGERR) { - if (flags & NV_RX2_SUBSTRACT1) { - len--; - } - } - /* the rest are hard errors */ - else { - if (flags & NV_RX2_CRCERR) - np->stats.rx_crc_errors++; - if (flags & NV_RX2_OVERFLOW) - np->stats.rx_over_errors++; - np->stats.rx_errors++; - dev_kfree_skb(skb); - goto next_pkt; - } - } - if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ { - skb->ip_summed = CHECKSUM_UNNECESSARY; - } else { - if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 || - (flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - } - } - } else { - dev_kfree_skb(skb); - goto next_pkt; - } + return -1; } - /* got a valid packet - forward it to the network core */ - skb_put(skb, len); - skb->protocol = eth_type_trans(skb, dev); - dprintk(KERN_DEBUG "%s: nv_rx_process: %d bytes, proto %d accepted.\n", - dev->name, len, skb->protocol); -#ifdef CONFIG_FORCEDETH_NAPI - netif_receive_skb(skb); -#else - netif_rx(skb); -#endif - dev->last_rx = jiffies; - np->stats.rx_packets++; - np->stats.rx_bytes += len; -next_pkt: - if (unlikely(np->get_rx.orig++ == np->last_rx.orig)) - np->get_rx.orig = np->first_rx.orig; - if (unlikely(np->get_rx_ctx++ == np->last_rx_ctx)) - np->get_rx_ctx = np->first_rx_ctx; + } else { + /* short packet. Accept only if 802 values are also short */ + if (protolen > ETH_ZLEN) { + dprintk(KERN_DEBUG "%s: nv_getlen: discarding short packet.\n", + dev->name); + return -1; + } + dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n", + dev->name, datalen); + return datalen; } - - return rx_processed_cnt; } -static int nv_rx_process_optimized(struct net_device *dev, int limit) +static int nv_rx_process(struct net_device *dev, int limit) { struct fe_priv *np = netdev_priv(dev); u32 flags; u32 vlanflags = 0; - u32 rx_processed_cnt = 0; - struct sk_buff *skb; - int len; + int count; - while((np->get_rx.ex != np->put_rx.ex) && - !((flags = le32_to_cpu(np->get_rx.ex->flaglen)) & NV_RX2_AVAIL) && - (rx_processed_cnt++ < limit)) { + for (count = 0; count < limit; ++count) { + struct sk_buff *skb; + int len; + int i; + if (np->cur_rx - np->refill_rx >= np->rx_ring_size) + break; /* we scanned the whole ring - do not continue */ + + i = np->cur_rx % np->rx_ring_size; + if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { + flags = le32_to_cpu(np->rx_ring.orig[i].flaglen); + len = nv_descr_getlength(&np->rx_ring.orig[i], np->desc_ver); + } else { + flags = le32_to_cpu(np->rx_ring.ex[i].flaglen); + len = nv_descr_getlength_ex(&np->rx_ring.ex[i], np->desc_ver); + vlanflags = le32_to_cpu(np->rx_ring.ex[i].buflow); + } + + dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, flags 0x%x.\n", + dev->name, np->cur_rx, flags); - dprintk(KERN_DEBUG "%s: nv_rx_process_optimized: flags 0x%x.\n", - dev->name, flags); + if (flags & NV_RX_AVAIL) + break; /* still owned by hardware, */ /* * the packet is for us - immediately tear down the pci mapping. * TODO: check if a prefetch of the first cacheline improves * the performance. */ - pci_unmap_single(np->pci_dev, np->get_rx_ctx->dma, - np->get_rx_ctx->dma_len, + pci_unmap_single(np->pci_dev, np->rx_dma[i], + np->rx_skbuff[i]->end-np->rx_skbuff[i]->data, PCI_DMA_FROMDEVICE); - skb = np->get_rx_ctx->skb; - np->get_rx_ctx->skb = NULL; { int j; @@ -2281,90 +1864,123 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit) for (j=0; j<64; j++) { if ((j%16) == 0) dprintk("\n%03x:", j); - dprintk(" %02x", ((unsigned char*)skb->data)[j]); + dprintk(" %02x", ((unsigned char*)np->rx_skbuff[i]->data)[j]); } dprintk("\n"); } /* look at what we actually got: */ - if (likely(flags & NV_RX2_DESCRIPTORVALID)) { - len = flags & LEN_MASK_V2; - if (unlikely(flags & NV_RX2_ERROR)) { + if (np->desc_ver == DESC_VER_1) { + if (!(flags & NV_RX_DESCRIPTORVALID)) + goto next_pkt; + + if (flags & NV_RX_ERROR) { + if (flags & NV_RX_MISSEDFRAME) { + np->stats.rx_missed_errors++; + np->stats.rx_errors++; + goto next_pkt; + } + if (flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) { + np->stats.rx_errors++; + goto next_pkt; + } + if (flags & NV_RX_CRCERR) { + np->stats.rx_crc_errors++; + np->stats.rx_errors++; + goto next_pkt; + } + if (flags & NV_RX_OVERFLOW) { + np->stats.rx_over_errors++; + np->stats.rx_errors++; + goto next_pkt; + } + if (flags & NV_RX_ERROR4) { + len = nv_getlen(dev, np->rx_skbuff[i]->data, len); + if (len < 0) { + np->stats.rx_errors++; + goto next_pkt; + } + } + /* framing errors are soft errors. */ + if (flags & NV_RX_FRAMINGERR) { + if (flags & NV_RX_SUBSTRACT1) { + len--; + } + } + } + } else { + if (!(flags & NV_RX2_DESCRIPTORVALID)) + goto next_pkt; + + if (flags & NV_RX2_ERROR) { + if (flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) { + np->stats.rx_errors++; + goto next_pkt; + } + if (flags & NV_RX2_CRCERR) { + np->stats.rx_crc_errors++; + np->stats.rx_errors++; + goto next_pkt; + } + if (flags & NV_RX2_OVERFLOW) { + np->stats.rx_over_errors++; + np->stats.rx_errors++; + goto next_pkt; + } if (flags & NV_RX2_ERROR4) { - len = nv_getlen(dev, skb->data, len); + len = nv_getlen(dev, np->rx_skbuff[i]->data, len); if (len < 0) { - dev_kfree_skb(skb); + np->stats.rx_errors++; goto next_pkt; } } /* framing errors are soft errors */ - else if (flags & NV_RX2_FRAMINGERR) { + if (flags & NV_RX2_FRAMINGERR) { if (flags & NV_RX2_SUBSTRACT1) { len--; } } - /* the rest are hard errors */ - else { - dev_kfree_skb(skb); - goto next_pkt; - } } - - if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ { - skb->ip_summed = CHECKSUM_UNNECESSARY; - } else { - if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 || - (flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) { - skb->ip_summed = CHECKSUM_UNNECESSARY; + if (np->rx_csum) { + flags &= NV_RX2_CHECKSUMMASK; + if (flags == NV_RX2_CHECKSUMOK1 || + flags == NV_RX2_CHECKSUMOK2 || + flags == NV_RX2_CHECKSUMOK3) { + dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name); + np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY; + } else { + dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name); } } + } + /* got a valid packet - forward it to the network core */ + skb = np->rx_skbuff[i]; + np->rx_skbuff[i] = NULL; - /* got a valid packet - forward it to the network core */ - skb_put(skb, len); - skb->protocol = eth_type_trans(skb, dev); - prefetch(skb->data); - - dprintk(KERN_DEBUG "%s: nv_rx_process_optimized: %d bytes, proto %d accepted.\n", - dev->name, len, skb->protocol); - - if (likely(!np->vlangrp)) { -#ifdef CONFIG_FORCEDETH_NAPI - netif_receive_skb(skb); -#else - netif_rx(skb); -#endif - } else { - vlanflags = le32_to_cpu(np->get_rx.ex->buflow); - if (vlanflags & NV_RX3_VLAN_TAG_PRESENT) { -#ifdef CONFIG_FORCEDETH_NAPI - vlan_hwaccel_receive_skb(skb, np->vlangrp, - vlanflags & NV_RX3_VLAN_TAG_MASK); -#else - vlan_hwaccel_rx(skb, np->vlangrp, - vlanflags & NV_RX3_VLAN_TAG_MASK); -#endif - } else { + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, dev); + dprintk(KERN_DEBUG "%s: nv_rx_process: packet %d with %d bytes, proto %d accepted.\n", + dev->name, np->cur_rx, len, skb->protocol); #ifdef CONFIG_FORCEDETH_NAPI - netif_receive_skb(skb); + if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT)) + vlan_hwaccel_receive_skb(skb, np->vlangrp, + vlanflags & NV_RX3_VLAN_TAG_MASK); + else + netif_receive_skb(skb); #else - netif_rx(skb); + if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT)) + vlan_hwaccel_rx(skb, np->vlangrp, + vlanflags & NV_RX3_VLAN_TAG_MASK); + else + netif_rx(skb); #endif - } - } - - dev->last_rx = jiffies; - np->stats.rx_packets++; - np->stats.rx_bytes += len; - } else { - dev_kfree_skb(skb); - } + dev->last_rx = jiffies; + np->stats.rx_packets++; + np->stats.rx_bytes += len; next_pkt: - if (unlikely(np->get_rx.ex++ == np->last_rx.ex)) - np->get_rx.ex = np->first_rx.ex; - if (unlikely(np->get_rx_ctx++ == np->last_rx_ctx)) - np->get_rx_ctx = np->first_rx_ctx; + np->cur_rx++; } - return rx_processed_cnt; + return count; } static void set_bufsize(struct net_device *dev) @@ -2840,6 +2456,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data) events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); } + pci_push(base); dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) break; @@ -2848,46 +2465,22 @@ static irqreturn_t nv_nic_irq(int foo, void *data) nv_tx_done(dev); spin_unlock(&np->lock); -#ifdef CONFIG_FORCEDETH_NAPI - if (events & NVREG_IRQ_RX_ALL) { - netif_rx_schedule(dev); - - /* Disable furthur receive irq's */ - spin_lock(&np->lock); - np->irqmask &= ~NVREG_IRQ_RX_ALL; - - if (np->msi_flags & NV_MSI_X_ENABLED) - writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - spin_unlock(&np->lock); - } -#else - if (nv_rx_process(dev, dev->weight)) { - if (unlikely(nv_alloc_rx(dev))) { - spin_lock(&np->lock); - if (!np->in_shutdown) - mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock(&np->lock); - } - } -#endif - if (unlikely(events & NVREG_IRQ_LINK)) { + if (events & NVREG_IRQ_LINK) { spin_lock(&np->lock); nv_link_irq(dev); spin_unlock(&np->lock); } - if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { + if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { spin_lock(&np->lock); nv_linkchange(dev); spin_unlock(&np->lock); np->link_timeout = jiffies + LINK_TIMEOUT; } - if (unlikely(events & (NVREG_IRQ_TX_ERR))) { + if (events & (NVREG_IRQ_TX_ERR)) { dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dev->name, events); } - if (unlikely(events & (NVREG_IRQ_UNKNOWN))) { + if (events & (NVREG_IRQ_UNKNOWN)) { printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", dev->name, events); } @@ -2908,63 +2501,6 @@ static irqreturn_t nv_nic_irq(int foo, void *data) spin_unlock(&np->lock); break; } - if (unlikely(i > max_interrupt_work)) { - spin_lock(&np->lock); - /* disable interrupts on the nic */ - if (!(np->msi_flags & NV_MSI_X_ENABLED)) - writel(0, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - pci_push(base); - - if (!np->in_shutdown) { - np->nic_poll_irq = np->irqmask; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); - } - printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq.\n", dev->name, i); - spin_unlock(&np->lock); - break; - } - - } - dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name); - - return IRQ_RETVAL(i); -} - -#define TX_WORK_PER_LOOP 64 -#define RX_WORK_PER_LOOP 64 -/** - * All _optimized functions are used to help increase performance - * (reduce CPU and increase throughput). They use descripter version 3, - * compiler directives, and reduce memory accesses. - */ -static irqreturn_t nv_nic_irq_optimized(int foo, void *data) -{ - struct net_device *dev = (struct net_device *) data; - struct fe_priv *np = netdev_priv(dev); - u8 __iomem *base = get_hwbase(dev); - u32 events; - int i; - - dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized\n", dev->name); - - for (i=0; ; i++) { - if (!(np->msi_flags & NV_MSI_X_ENABLED)) { - events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK; - writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); - } else { - events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; - writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus); - } - dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); - if (!(events & np->irqmask)) - break; - - spin_lock(&np->lock); - nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); - spin_unlock(&np->lock); - #ifdef CONFIG_FORCEDETH_NAPI if (events & NVREG_IRQ_RX_ALL) { netif_rx_schedule(dev); @@ -2980,53 +2516,15 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) spin_unlock(&np->lock); } #else - if (nv_rx_process_optimized(dev, dev->weight)) { - if (unlikely(nv_alloc_rx_optimized(dev))) { - spin_lock(&np->lock); - if (!np->in_shutdown) - mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock(&np->lock); - } - } -#endif - if (unlikely(events & NVREG_IRQ_LINK)) { - spin_lock(&np->lock); - nv_link_irq(dev); - spin_unlock(&np->lock); - } - if (unlikely(np->need_linktimer && time_after(jiffies, np->link_timeout))) { - spin_lock(&np->lock); - nv_linkchange(dev); - spin_unlock(&np->lock); - np->link_timeout = jiffies + LINK_TIMEOUT; - } - if (unlikely(events & (NVREG_IRQ_TX_ERR))) { - dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", - dev->name, events); - } - if (unlikely(events & (NVREG_IRQ_UNKNOWN))) { - printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", - dev->name, events); - } - if (unlikely(events & NVREG_IRQ_RECOVER_ERROR)) { + nv_rx_process(dev, dev->weight); + if (nv_alloc_rx(dev)) { spin_lock(&np->lock); - /* disable interrupts on the nic */ - if (!(np->msi_flags & NV_MSI_X_ENABLED)) - writel(0, base + NvRegIrqMask); - else - writel(np->irqmask, base + NvRegIrqMask); - pci_push(base); - - if (!np->in_shutdown) { - np->nic_poll_irq = np->irqmask; - np->recover_error = 1; - mod_timer(&np->nic_poll, jiffies + POLL_WAIT); - } + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); spin_unlock(&np->lock); - break; } - - if (unlikely(i > max_interrupt_work)) { +#endif + if (i > max_interrupt_work) { spin_lock(&np->lock); /* disable interrupts on the nic */ if (!(np->msi_flags & NV_MSI_X_ENABLED)) @@ -3045,7 +2543,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) } } - dprintk(KERN_DEBUG "%s: nv_nic_irq_optimized completed\n", dev->name); + dprintk(KERN_DEBUG "%s: nv_nic_irq completed\n", dev->name); return IRQ_RETVAL(i); } @@ -3064,19 +2562,20 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data) for (i=0; ; i++) { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL; writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus); + pci_push(base); dprintk(KERN_DEBUG "%s: tx irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) break; spin_lock_irqsave(&np->lock, flags); - nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); + nv_tx_done(dev); spin_unlock_irqrestore(&np->lock, flags); - if (unlikely(events & (NVREG_IRQ_TX_ERR))) { + if (events & (NVREG_IRQ_TX_ERR)) { dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dev->name, events); } - if (unlikely(i > max_interrupt_work)) { + if (i > max_interrupt_work) { spin_lock_irqsave(&np->lock, flags); /* disable interrupts on the nic */ writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); @@ -3105,10 +2604,7 @@ static int nv_napi_poll(struct net_device *dev, int *budget) u8 __iomem *base = get_hwbase(dev); unsigned long flags; - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - pkts = nv_rx_process(dev, limit); - else - pkts = nv_rx_process_optimized(dev, limit); + pkts = nv_rx_process(dev, limit); if (nv_alloc_rx(dev)) { spin_lock_irqsave(&np->lock, flags); @@ -3174,20 +2670,20 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data) for (i=0; ; i++) { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL; writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus); + pci_push(base); dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) break; - if (nv_rx_process_optimized(dev, dev->weight)) { - if (unlikely(nv_alloc_rx_optimized(dev))) { - spin_lock_irqsave(&np->lock, flags); - if (!np->in_shutdown) - mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock_irqrestore(&np->lock, flags); - } + nv_rx_process(dev, dev->weight); + if (nv_alloc_rx(dev)) { + spin_lock_irqsave(&np->lock, flags); + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); + spin_unlock_irqrestore(&np->lock, flags); } - if (unlikely(i > max_interrupt_work)) { + if (i > max_interrupt_work) { spin_lock_irqsave(&np->lock, flags); /* disable interrupts on the nic */ writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); @@ -3222,15 +2718,11 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) for (i=0; ; i++) { events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_OTHER; writel(NVREG_IRQ_OTHER, base + NvRegMSIXIrqStatus); + pci_push(base); dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events); if (!(events & np->irqmask)) break; - /* check tx in case we reached max loop limit in tx isr */ - spin_lock_irqsave(&np->lock, flags); - nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); - spin_unlock_irqrestore(&np->lock, flags); - if (events & NVREG_IRQ_LINK) { spin_lock_irqsave(&np->lock, flags); nv_link_irq(dev); @@ -3260,7 +2752,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", dev->name, events); } - if (unlikely(i > max_interrupt_work)) { + if (i > max_interrupt_work) { spin_lock_irqsave(&np->lock, flags); /* disable interrupts on the nic */ writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); @@ -3343,16 +2835,6 @@ static int nv_request_irq(struct net_device *dev, int intr_test) u8 __iomem *base = get_hwbase(dev); int ret = 1; int i; - irqreturn_t (*handler)(int foo, void *data); - - if (intr_test) { - handler = nv_nic_irq_test; - } else { - if (np->desc_ver == DESC_VER_3) - handler = nv_nic_irq_optimized; - else - handler = nv_nic_irq; - } if (np->msi_flags & NV_MSI_X_CAPABLE) { for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { @@ -3390,7 +2872,10 @@ static int nv_request_irq(struct net_device *dev, int intr_test) set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); } else { /* Request irq for all interrupts */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, handler, IRQF_SHARED, dev->name, dev) != 0) { + if ((!intr_test && + request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, IRQF_SHARED, dev->name, dev) != 0) || + (intr_test && + request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq_test, IRQF_SHARED, dev->name, dev) != 0)) { printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); pci_disable_msix(np->pci_dev); np->msi_flags &= ~NV_MSI_X_ENABLED; @@ -3406,7 +2891,8 @@ static int nv_request_irq(struct net_device *dev, int intr_test) if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { if ((ret = pci_enable_msi(np->pci_dev)) == 0) { np->msi_flags |= NV_MSI_ENABLED; - if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) { + if ((!intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq, IRQF_SHARED, dev->name, dev) != 0) || + (intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq_test, IRQF_SHARED, dev->name, dev) != 0)) { printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); pci_disable_msi(np->pci_dev); np->msi_flags &= ~NV_MSI_ENABLED; @@ -3421,7 +2907,8 @@ static int nv_request_irq(struct net_device *dev, int intr_test) } } if (ret != 0) { - if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) + if ((!intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq, IRQF_SHARED, dev->name, dev) != 0) || + (intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq_test, IRQF_SHARED, dev->name, dev) != 0)) goto out_err; } @@ -3564,8 +3051,47 @@ static void nv_do_stats_poll(unsigned long data) { struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); - nv_get_hw_stats(dev); + np->estats.tx_bytes += readl(base + NvRegTxCnt); + np->estats.tx_zero_rexmt += readl(base + NvRegTxZeroReXmt); + np->estats.tx_one_rexmt += readl(base + NvRegTxOneReXmt); + np->estats.tx_many_rexmt += readl(base + NvRegTxManyReXmt); + np->estats.tx_late_collision += readl(base + NvRegTxLateCol); + np->estats.tx_fifo_errors += readl(base + NvRegTxUnderflow); + np->estats.tx_carrier_errors += readl(base + NvRegTxLossCarrier); + np->estats.tx_excess_deferral += readl(base + NvRegTxExcessDef); + np->estats.tx_retry_error += readl(base + NvRegTxRetryErr); + np->estats.tx_deferral += readl(base + NvRegTxDef); + np->estats.tx_packets += readl(base + NvRegTxFrame); + np->estats.tx_pause += readl(base + NvRegTxPause); + np->estats.rx_frame_error += readl(base + NvRegRxFrameErr); + np->estats.rx_extra_byte += readl(base + NvRegRxExtraByte); + np->estats.rx_late_collision += readl(base + NvRegRxLateCol); + np->estats.rx_runt += readl(base + NvRegRxRunt); + np->estats.rx_frame_too_long += readl(base + NvRegRxFrameTooLong); + np->estats.rx_over_errors += readl(base + NvRegRxOverflow); + np->estats.rx_crc_errors += readl(base + NvRegRxFCSErr); + np->estats.rx_frame_align_error += readl(base + NvRegRxFrameAlignErr); + np->estats.rx_length_error += readl(base + NvRegRxLenErr); + np->estats.rx_unicast += readl(base + NvRegRxUnicast); + np->estats.rx_multicast += readl(base + NvRegRxMulticast); + np->estats.rx_broadcast += readl(base + NvRegRxBroadcast); + np->estats.rx_bytes += readl(base + NvRegRxCnt); + np->estats.rx_pause += readl(base + NvRegRxPause); + np->estats.rx_drop_frame += readl(base + NvRegRxDropFrame); + np->estats.rx_packets = + np->estats.rx_unicast + + np->estats.rx_multicast + + np->estats.rx_broadcast; + np->estats.rx_errors_total = + np->estats.rx_crc_errors + + np->estats.rx_over_errors + + np->estats.rx_frame_error + + (np->estats.rx_frame_align_error - np->estats.rx_extra_byte) + + np->estats.rx_late_collision + + np->estats.rx_runt + + np->estats.rx_frame_too_long; if (!np->in_shutdown) mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL); @@ -3939,7 +3465,7 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - u8 *rxtx_ring, *rx_skbuff, *tx_skbuff; + u8 *rxtx_ring, *rx_skbuff, *tx_skbuff, *rx_dma, *tx_dma, *tx_dma_len; dma_addr_t ring_addr; if (ring->rx_pending < RX_RING_MIN || @@ -3965,9 +3491,12 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending), &ring_addr); } - rx_skbuff = kmalloc(sizeof(struct nv_skb_map) * ring->rx_pending, GFP_KERNEL); - tx_skbuff = kmalloc(sizeof(struct nv_skb_map) * ring->tx_pending, GFP_KERNEL); - if (!rxtx_ring || !rx_skbuff || !tx_skbuff) { + rx_skbuff = kmalloc(sizeof(struct sk_buff*) * ring->rx_pending, GFP_KERNEL); + rx_dma = kmalloc(sizeof(dma_addr_t) * ring->rx_pending, GFP_KERNEL); + tx_skbuff = kmalloc(sizeof(struct sk_buff*) * ring->tx_pending, GFP_KERNEL); + tx_dma = kmalloc(sizeof(dma_addr_t) * ring->tx_pending, GFP_KERNEL); + tx_dma_len = kmalloc(sizeof(unsigned int) * ring->tx_pending, GFP_KERNEL); + if (!rxtx_ring || !rx_skbuff || !rx_dma || !tx_skbuff || !tx_dma || !tx_dma_len) { /* fall back to old rings */ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { if (rxtx_ring) @@ -3980,8 +3509,14 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri } if (rx_skbuff) kfree(rx_skbuff); + if (rx_dma) + kfree(rx_dma); if (tx_skbuff) kfree(tx_skbuff); + if (tx_dma) + kfree(tx_dma); + if (tx_dma_len) + kfree(tx_dma_len); goto exit; } @@ -4003,6 +3538,8 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri /* set new values */ np->rx_ring_size = ring->rx_pending; np->tx_ring_size = ring->tx_pending; + np->tx_limit_stop = ring->tx_pending - TX_LIMIT_DIFFERENCE; + np->tx_limit_start = ring->tx_pending - TX_LIMIT_DIFFERENCE - 1; if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { np->rx_ring.orig = (struct ring_desc*)rxtx_ring; np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size]; @@ -4010,12 +3547,18 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri np->rx_ring.ex = (struct ring_desc_ex*)rxtx_ring; np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size]; } - np->rx_skb = (struct nv_skb_map*)rx_skbuff; - np->tx_skb = (struct nv_skb_map*)tx_skbuff; + np->rx_skbuff = (struct sk_buff**)rx_skbuff; + np->rx_dma = (dma_addr_t*)rx_dma; + np->tx_skbuff = (struct sk_buff**)tx_skbuff; + np->tx_dma = (dma_addr_t*)tx_dma; + np->tx_dma_len = (unsigned int*)tx_dma_len; np->ring_addr = ring_addr; - memset(np->rx_skb, 0, sizeof(struct nv_skb_map) * np->rx_ring_size); - memset(np->tx_skb, 0, sizeof(struct nv_skb_map) * np->tx_ring_size); + memset(np->rx_skbuff, 0, sizeof(struct sk_buff*) * np->rx_ring_size); + memset(np->rx_dma, 0, sizeof(dma_addr_t) * np->rx_ring_size); + memset(np->tx_skbuff, 0, sizeof(struct sk_buff*) * np->tx_ring_size); + memset(np->tx_dma, 0, sizeof(dma_addr_t) * np->tx_ring_size); + memset(np->tx_dma_len, 0, sizeof(unsigned int) * np->tx_ring_size); if (netif_running(dev)) { /* reinit driver view of the queues */ @@ -4184,10 +3727,8 @@ static int nv_get_stats_count(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); - if (np->driver_data & DEV_HAS_STATISTICS_V1) - return NV_DEV_STATISTICS_V1_COUNT; - else if (np->driver_data & DEV_HAS_STATISTICS_V2) - return NV_DEV_STATISTICS_V2_COUNT; + if (np->driver_data & DEV_HAS_STATISTICS) + return sizeof(struct nv_ethtool_stats)/sizeof(u64); else return 0; } @@ -4414,7 +3955,7 @@ static int nv_loopback_test(struct net_device *dev) dprintk(KERN_DEBUG "%s: loopback len mismatch %d vs %d\n", dev->name, len, pkt_len); } else { - rx_skb = np->rx_skb[0].skb; + rx_skb = np->rx_skbuff[0]; for (i = 0; i < pkt_len; i++) { if (rx_skb->data[i] != (u8)(i & 0xff)) { ret = 0; @@ -4774,7 +4315,7 @@ static int nv_open(struct net_device *dev) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); /* start statistics timer */ - if (np->driver_data & (DEV_HAS_STATISTICS_V1|DEV_HAS_STATISTICS_V2)) + if (np->driver_data & DEV_HAS_STATISTICS) mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL); spin_unlock_irq(&np->lock); @@ -4871,9 +4412,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i if (err < 0) goto out_disable; - if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V2)) - np->register_size = NV_PCI_REGSZ_VER3; - else if (id->driver_data & DEV_HAS_STATISTICS_V1) + if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS)) np->register_size = NV_PCI_REGSZ_VER2; else np->register_size = NV_PCI_REGSZ_VER1; @@ -4936,8 +4475,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->rx_csum = 1; np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; +#ifdef NETIF_F_TSO dev->features |= NETIF_F_TSO; - } +#endif + } np->vlanctl_bits = 0; if (id->driver_data & DEV_HAS_VLAN) { @@ -4971,6 +4512,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->rx_ring_size = RX_RING_DEFAULT; np->tx_ring_size = TX_RING_DEFAULT; + np->tx_limit_stop = np->tx_ring_size - TX_LIMIT_DIFFERENCE; + np->tx_limit_start = np->tx_ring_size - TX_LIMIT_DIFFERENCE - 1; if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { np->rx_ring.orig = pci_alloc_consistent(pci_dev, @@ -4987,19 +4530,22 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i goto out_unmap; np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size]; } - np->rx_skb = kmalloc(sizeof(struct nv_skb_map) * np->rx_ring_size, GFP_KERNEL); - np->tx_skb = kmalloc(sizeof(struct nv_skb_map) * np->tx_ring_size, GFP_KERNEL); - if (!np->rx_skb || !np->tx_skb) + np->rx_skbuff = kmalloc(sizeof(struct sk_buff*) * np->rx_ring_size, GFP_KERNEL); + np->rx_dma = kmalloc(sizeof(dma_addr_t) * np->rx_ring_size, GFP_KERNEL); + np->tx_skbuff = kmalloc(sizeof(struct sk_buff*) * np->tx_ring_size, GFP_KERNEL); + np->tx_dma = kmalloc(sizeof(dma_addr_t) * np->tx_ring_size, GFP_KERNEL); + np->tx_dma_len = kmalloc(sizeof(unsigned int) * np->tx_ring_size, GFP_KERNEL); + if (!np->rx_skbuff || !np->rx_dma || !np->tx_skbuff || !np->tx_dma || !np->tx_dma_len) goto out_freering; - memset(np->rx_skb, 0, sizeof(struct nv_skb_map) * np->rx_ring_size); - memset(np->tx_skb, 0, sizeof(struct nv_skb_map) * np->tx_ring_size); + memset(np->rx_skbuff, 0, sizeof(struct sk_buff*) * np->rx_ring_size); + memset(np->rx_dma, 0, sizeof(dma_addr_t) * np->rx_ring_size); + memset(np->tx_skbuff, 0, sizeof(struct sk_buff*) * np->tx_ring_size); + memset(np->tx_dma, 0, sizeof(dma_addr_t) * np->tx_ring_size); + memset(np->tx_dma_len, 0, sizeof(unsigned int) * np->tx_ring_size); dev->open = nv_open; dev->stop = nv_close; - if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) - dev->hard_start_xmit = nv_start_xmit; - else - dev->hard_start_xmit = nv_start_xmit_optimized; + dev->hard_start_xmit = nv_start_xmit; dev->get_stats = nv_get_stats; dev->change_mtu = nv_change_mtu; dev->set_mac_address = nv_set_mac_address; @@ -5007,7 +4553,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = nv_poll_controller; #endif - dev->weight = RX_WORK_PER_LOOP; + dev->weight = 64; #ifdef CONFIG_FORCEDETH_NAPI dev->poll = nv_napi_poll; #endif @@ -5322,83 +4868,83 @@ static struct pci_device_id pci_tbl[] = { }, { /* CK804 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA, }, { /* CK804 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA, }, { /* MCP04 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA, }, { /* MCP04 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_STATISTICS_V1, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA, }, { /* MCP51 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, }, { /* MCP51 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS_V1, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, {0,}, }; diff --git a/trunk/drivers/net/hp100.c b/trunk/drivers/net/hp100.c index 7dc5185aa2c0..844c136e9920 100644 --- a/trunk/drivers/net/hp100.c +++ b/trunk/drivers/net/hp100.c @@ -3034,7 +3034,7 @@ static int __init hp100_module_init(void) goto out2; #endif #ifdef CONFIG_PCI - err = pci_register_driver(&hp100_pci_driver); + err = pci_module_init(&hp100_pci_driver); if (err && err != -ENODEV) goto out3; #endif diff --git a/trunk/drivers/net/iseries_veth.c b/trunk/drivers/net/iseries_veth.c index 0e9ba3c3faf7..2194b567239f 100644 --- a/trunk/drivers/net/iseries_veth.c +++ b/trunk/drivers/net/iseries_veth.c @@ -1102,7 +1102,7 @@ static struct net_device * __init veth_probe_one(int vlan, } kobject_init(&port->kobject); - port->kobject.parent = &dev->dev.kobj; + port->kobject.parent = &dev->class_dev.kobj; port->kobject.ktype = &veth_port_ktype; kobject_set_name(&port->kobject, "veth_port"); if (0 != kobject_add(&port->kobject)) diff --git a/trunk/drivers/net/ixgb/ixgb.h b/trunk/drivers/net/ixgb/ixgb.h index cf30a1059ce0..f4aba4355b19 100644 --- a/trunk/drivers/net/ixgb/ixgb.h +++ b/trunk/drivers/net/ixgb/ixgb.h @@ -61,7 +61,9 @@ #include #include #include +#ifdef NETIF_F_TSO #include +#endif #include #include diff --git a/trunk/drivers/net/ixgb/ixgb_ethtool.c b/trunk/drivers/net/ixgb/ixgb_ethtool.c index d6628bd9590a..82c044d6e08a 100644 --- a/trunk/drivers/net/ixgb/ixgb_ethtool.c +++ b/trunk/drivers/net/ixgb/ixgb_ethtool.c @@ -82,8 +82,10 @@ static struct ixgb_stats ixgb_gstrings_stats[] = { {"tx_restart_queue", IXGB_STAT(restart_queue) }, {"rx_long_length_errors", IXGB_STAT(stats.roc)}, {"rx_short_length_errors", IXGB_STAT(stats.ruc)}, +#ifdef NETIF_F_TSO {"tx_tcp_seg_good", IXGB_STAT(stats.tsctc)}, {"tx_tcp_seg_failed", IXGB_STAT(stats.tsctfc)}, +#endif {"rx_flow_control_xon", IXGB_STAT(stats.xonrxc)}, {"rx_flow_control_xoff", IXGB_STAT(stats.xoffrxc)}, {"tx_flow_control_xon", IXGB_STAT(stats.xontxc)}, @@ -238,6 +240,7 @@ ixgb_set_tx_csum(struct net_device *netdev, uint32_t data) return 0; } +#ifdef NETIF_F_TSO static int ixgb_set_tso(struct net_device *netdev, uint32_t data) { @@ -247,6 +250,7 @@ ixgb_set_tso(struct net_device *netdev, uint32_t data) netdev->features &= ~NETIF_F_TSO; return 0; } +#endif /* NETIF_F_TSO */ static uint32_t ixgb_get_msglevel(struct net_device *netdev) @@ -718,8 +722,10 @@ static const struct ethtool_ops ixgb_ethtool_ops = { .set_sg = ethtool_op_set_sg, .get_msglevel = ixgb_get_msglevel, .set_msglevel = ixgb_set_msglevel, +#ifdef NETIF_F_TSO .get_tso = ethtool_op_get_tso, .set_tso = ixgb_set_tso, +#endif .get_strings = ixgb_get_strings, .phys_id = ixgb_phys_id, .get_stats_count = ixgb_get_stats_count, diff --git a/trunk/drivers/net/ixgb/ixgb_main.c b/trunk/drivers/net/ixgb/ixgb_main.c index 0c3682889344..a083a9189230 100644 --- a/trunk/drivers/net/ixgb/ixgb_main.c +++ b/trunk/drivers/net/ixgb/ixgb_main.c @@ -456,7 +456,9 @@ ixgb_probe(struct pci_dev *pdev, NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; +#ifdef NETIF_F_TSO netdev->features |= NETIF_F_TSO; +#endif #ifdef NETIF_F_LLTX netdev->features |= NETIF_F_LLTX; #endif @@ -1174,6 +1176,7 @@ ixgb_watchdog(unsigned long data) static int ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb) { +#ifdef NETIF_F_TSO struct ixgb_context_desc *context_desc; unsigned int i; uint8_t ipcss, ipcso, tucss, tucso, hdr_len; @@ -1230,6 +1233,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb) return 1; } +#endif return 0; } @@ -1605,7 +1609,7 @@ ixgb_update_stats(struct ixgb_adapter *adapter) struct pci_dev *pdev = adapter->pdev; /* Prevent stats update while adapter is being reset */ - if (pci_channel_offline(pdev)) + if (pdev->error_state && pdev->error_state != pci_channel_io_normal) return; if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) || diff --git a/trunk/drivers/net/macb.c b/trunk/drivers/net/macb.c index e67361e2bf5d..25b559b5d5ed 100644 --- a/trunk/drivers/net/macb.c +++ b/trunk/drivers/net/macb.c @@ -27,6 +27,8 @@ #include "macb.h" +#define to_net_dev(class) container_of(class, struct net_device, class_dev) + #define RX_BUFFER_SIZE 128 #define RX_RING_SIZE 512 #define RX_RING_BYTES (sizeof(struct dma_desc) * RX_RING_SIZE) @@ -943,10 +945,10 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return ret; } -static ssize_t macb_mii_show(const struct device *_dev, char *buf, +static ssize_t macb_mii_show(const struct class_device *cd, char *buf, unsigned long addr) { - struct net_device *dev = to_net_dev(_dev); + struct net_device *dev = to_net_dev(cd); struct macb *bp = netdev_priv(dev); ssize_t ret = -EINVAL; @@ -960,13 +962,11 @@ static ssize_t macb_mii_show(const struct device *_dev, char *buf, } #define MII_ENTRY(name, addr) \ -static ssize_t show_##name(struct device *_dev, \ - struct device_attribute *attr, \ - char *buf) \ +static ssize_t show_##name(struct class_device *cd, char *buf) \ { \ - return macb_mii_show(_dev, buf, addr); \ + return macb_mii_show(cd, buf, addr); \ } \ -static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) +static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) MII_ENTRY(bmcr, MII_BMCR); MII_ENTRY(bmsr, MII_BMSR); @@ -977,13 +977,13 @@ MII_ENTRY(lpa, MII_LPA); MII_ENTRY(expansion, MII_EXPANSION); static struct attribute *macb_mii_attrs[] = { - &dev_attr_bmcr.attr, - &dev_attr_bmsr.attr, - &dev_attr_physid1.attr, - &dev_attr_physid2.attr, - &dev_attr_advertise.attr, - &dev_attr_lpa.attr, - &dev_attr_expansion.attr, + &class_device_attr_bmcr.attr, + &class_device_attr_bmsr.attr, + &class_device_attr_physid1.attr, + &class_device_attr_physid2.attr, + &class_device_attr_advertise.attr, + &class_device_attr_lpa.attr, + &class_device_attr_expansion.attr, NULL, }; @@ -994,17 +994,17 @@ static struct attribute_group macb_mii_group = { static void macb_unregister_sysfs(struct net_device *net) { - struct device *_dev = &net->dev; + struct class_device *class_dev = &net->class_dev; - sysfs_remove_group(&_dev->kobj, &macb_mii_group); + sysfs_remove_group(&class_dev->kobj, &macb_mii_group); } static int macb_register_sysfs(struct net_device *net) { - struct device *_dev = &net->dev; + struct class_device *class_dev = &net->class_dev; int ret; - ret = sysfs_create_group(&_dev->kobj, &macb_mii_group); + ret = sysfs_create_group(&class_dev->kobj, &macb_mii_group); if (ret) printk(KERN_WARNING "%s: sysfs mii attribute registration failed: %d\n", @@ -1046,14 +1046,6 @@ static int __devinit macb_probe(struct platform_device *pdev) spin_lock_init(&bp->lock); -#if defined(CONFIG_ARCH_AT91) - bp->pclk = clk_get(&pdev->dev, "macb_clk"); - if (IS_ERR(bp->pclk)) { - dev_err(&pdev->dev, "failed to get macb_clk\n"); - goto err_out_free_dev; - } - clk_enable(bp->pclk); -#else bp->pclk = clk_get(&pdev->dev, "pclk"); if (IS_ERR(bp->pclk)) { dev_err(&pdev->dev, "failed to get pclk\n"); @@ -1067,7 +1059,6 @@ static int __devinit macb_probe(struct platform_device *pdev) clk_enable(bp->pclk); clk_enable(bp->hclk); -#endif bp->regs = ioremap(regs->start, regs->end - regs->start + 1); if (!bp->regs) { @@ -1128,17 +1119,9 @@ static int __devinit macb_probe(struct platform_device *pdev) pdata = pdev->dev.platform_data; if (pdata && pdata->is_rmii) -#if defined(CONFIG_ARCH_AT91) - macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) ); -#else macb_writel(bp, USRIO, 0); -#endif else -#if defined(CONFIG_ARCH_AT91) - macb_writel(bp, USRIO, MACB_BIT(CLKEN)); -#else macb_writel(bp, USRIO, MACB_BIT(MII)); -#endif bp->tx_pending = DEF_TX_RING_PENDING; @@ -1165,11 +1148,9 @@ static int __devinit macb_probe(struct platform_device *pdev) err_out_iounmap: iounmap(bp->regs); err_out_disable_clocks: -#ifndef CONFIG_ARCH_AT91 clk_disable(bp->hclk); - clk_put(bp->hclk); -#endif clk_disable(bp->pclk); + clk_put(bp->hclk); err_out_put_pclk: clk_put(bp->pclk); err_out_free_dev: @@ -1192,11 +1173,9 @@ static int __devexit macb_remove(struct platform_device *pdev) unregister_netdev(dev); free_irq(dev->irq, dev); iounmap(bp->regs); -#ifndef CONFIG_ARCH_AT91 clk_disable(bp->hclk); - clk_put(bp->hclk); -#endif clk_disable(bp->pclk); + clk_put(bp->hclk); clk_put(bp->pclk); free_netdev(dev); platform_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/net/macb.h b/trunk/drivers/net/macb.h index b3bb2182edd1..27bf0ae0f0bb 100644 --- a/trunk/drivers/net/macb.h +++ b/trunk/drivers/net/macb.h @@ -200,7 +200,7 @@ #define MACB_SOF_OFFSET 30 #define MACB_SOF_SIZE 2 -/* Bitfields in USRIO (AVR32) */ +/* Bitfields in USRIO */ #define MACB_MII_OFFSET 0 #define MACB_MII_SIZE 1 #define MACB_EAM_OFFSET 1 @@ -210,12 +210,6 @@ #define MACB_TX_PAUSE_ZERO_OFFSET 3 #define MACB_TX_PAUSE_ZERO_SIZE 1 -/* Bitfields in USRIO (AT91) */ -#define MACB_RMII_OFFSET 0 -#define MACB_RMII_SIZE 1 -#define MACB_CLKEN_OFFSET 1 -#define MACB_CLKEN_SIZE 1 - /* Bitfields in WOL */ #define MACB_IP_OFFSET 0 #define MACB_IP_SIZE 16 diff --git a/trunk/drivers/net/mace.c b/trunk/drivers/net/mace.c index 9ec24f0d5d68..2907cfb12ada 100644 --- a/trunk/drivers/net/mace.c +++ b/trunk/drivers/net/mace.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -75,6 +74,7 @@ struct mace_data { #define PRIV_BYTES (sizeof(struct mace_data) \ + (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd)) +static int bitrev(int); static int mace_open(struct net_device *dev); static int mace_close(struct net_device *dev); static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev); @@ -96,6 +96,18 @@ static void __mace_set_address(struct net_device *dev, void *addr); */ static unsigned char *dummy_buf; +/* Bit-reverse one byte of an ethernet hardware address. */ +static inline int +bitrev(int b) +{ + int d = 0, i; + + for (i = 0; i < 8; ++i, b >>= 1) + d = (d << 1) | (b & 1); + return d; +} + + static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match) { struct device_node *mace = macio_get_of_node(mdev); @@ -161,7 +173,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i rev = addr[0] == 0 && addr[1] == 0xA0; for (j = 0; j < 6; ++j) { - dev->dev_addr[j] = rev ? bitrev8(addr[j]): addr[j]; + dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j]; } mp->chipid = (in_8(&mp->mace->chipid_hi) << 8) | in_8(&mp->mace->chipid_lo); diff --git a/trunk/drivers/net/macmace.c b/trunk/drivers/net/macmace.c index 5d541e873041..464e4a6f3d5f 100644 --- a/trunk/drivers/net/macmace.c +++ b/trunk/drivers/net/macmace.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -82,6 +81,19 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id); static irqreturn_t mace_dma_intr(int irq, void *dev_id); static void mace_tx_timeout(struct net_device *dev); +/* Bit-reverse one byte of an ethernet hardware address. */ + +static int bitrev(int b) +{ + int d = 0, i; + + for (i = 0; i < 8; ++i, b >>= 1) { + d = (d << 1) | (b & 1); + } + + return d; +} + /* * Load a receive DMA channel with a base address and ring length */ @@ -207,12 +219,12 @@ struct net_device *mace_probe(int unit) addr = (void *)MACE_PROM; for (j = 0; j < 6; ++j) { - u8 v = bitrev8(addr[j<<4]); + u8 v=bitrev(addr[j<<4]); checksum ^= v; dev->dev_addr[j] = v; } for (; j < 8; ++j) { - checksum ^= bitrev8(addr[j<<4]); + checksum ^= bitrev(addr[j<<4]); } if (checksum != 0xFF) { diff --git a/trunk/drivers/net/macsonic.c b/trunk/drivers/net/macsonic.c index 24f6050fbf33..393d995f1919 100644 --- a/trunk/drivers/net/macsonic.c +++ b/trunk/drivers/net/macsonic.c @@ -121,12 +121,16 @@ enum macsonic_type { * For reversing the PROM address */ +static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14, + 1, 9, 5, 13, 3, 11, 7, 15}; + static inline void bit_reverse_addr(unsigned char addr[6]) { int i; for(i = 0; i < 6; i++) - addr[i] = bitrev8(addr[i]); + addr[i] = ((nibbletab[addr[i] & 0xf] << 4) | + nibbletab[(addr[i] >> 4) &0xf]); } int __init macsonic_init(struct net_device* dev) diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 030924fb1ab3..61cbd4a60446 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -1412,8 +1412,10 @@ static const struct ethtool_ops myri10ge_ethtool_ops = { .set_tx_csum = ethtool_op_set_tx_hw_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, +#endif .get_strings = myri10ge_get_strings, .get_stats_count = myri10ge_get_stats_count, .get_ethtool_stats = myri10ge_get_ethtool_stats, @@ -1973,11 +1975,13 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) mss = 0; max_segments = MXGEFW_MAX_SEND_DESC; +#ifdef NETIF_F_TSO if (skb->len > (dev->mtu + ETH_HLEN)) { mss = skb_shinfo(skb)->gso_size; if (mss != 0) max_segments = MYRI10GE_MAX_SEND_DESC_TSO; } +#endif /*NETIF_F_TSO */ if ((unlikely(avail < max_segments))) { /* we are out of transmit resources */ @@ -2009,6 +2013,7 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) cum_len = 0; +#ifdef NETIF_F_TSO if (mss) { /* TSO */ /* this removes any CKSUM flag from before */ flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST); @@ -2024,6 +2029,7 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) * the checksum by parsing the header. */ pseudo_hdr_offset = mss; } else +#endif /*NETIF_F_TSO */ /* Mark small packets, and pad out tiny packets */ if (skb->len <= MXGEFW_SEND_SMALL_SIZE) { flags |= MXGEFW_FLAGS_SMALL; @@ -2091,6 +2097,7 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) seglen = len; flags_next = flags & ~MXGEFW_FLAGS_FIRST; cum_len_next = cum_len + seglen; +#ifdef NETIF_F_TSO if (mss) { /* TSO */ (req - rdma_count)->rdma_count = rdma_count + 1; @@ -2117,6 +2124,7 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) (small * MXGEFW_FLAGS_SMALL); } } +#endif /* NETIF_F_TSO */ req->addr_high = high_swapped; req->addr_low = htonl(low); req->pseudo_hdr_offset = htons(pseudo_hdr_offset); @@ -2153,12 +2161,14 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) } (req - rdma_count)->rdma_count = rdma_count; +#ifdef NETIF_F_TSO if (mss) do { req--; req->flags |= MXGEFW_FLAGS_TSO_LAST; } while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP | MXGEFW_FLAGS_FIRST))); +#endif idx = ((count - 1) + tx->req) & tx->mask; tx->info[idx].last = 1; if (tx->wc_fifo == NULL) diff --git a/trunk/drivers/net/netxen/netxen_nic.h b/trunk/drivers/net/netxen/netxen_nic.h index 3f3896e98879..e8598b809228 100644 --- a/trunk/drivers/net/netxen/netxen_nic.h +++ b/trunk/drivers/net/netxen/netxen_nic.h @@ -63,14 +63,11 @@ #include "netxen_nic_hw.h" +#define NETXEN_NIC_BUILD_NO "2" #define _NETXEN_NIC_LINUX_MAJOR 3 #define _NETXEN_NIC_LINUX_MINOR 3 #define _NETXEN_NIC_LINUX_SUBVERSION 3 -#define NETXEN_NIC_LINUX_VERSIONID "3.3.3" - -#define NUM_FLASH_SECTORS (64) -#define FLASH_SECTOR_SIZE (64 * 1024) -#define FLASH_TOTAL_SIZE (NUM_FLASH_SECTORS * FLASH_SECTOR_SIZE) +#define NETXEN_NIC_LINUX_VERSIONID "3.3.3" "-" NETXEN_NIC_BUILD_NO #define RCV_DESC_RINGSIZE \ (sizeof(struct rcv_desc) * adapter->max_rx_desc_count) @@ -88,7 +85,6 @@ #define NETXEN_RCV_PRODUCER_OFFSET 0 #define NETXEN_RCV_PEG_DB_ID 2 #define NETXEN_HOST_DUMMY_DMA_SIZE 1024 -#define FLASH_SUCCESS 0 #define ADDR_IN_WINDOW1(off) \ ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0 @@ -1032,15 +1028,6 @@ void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); void netxen_load_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); -int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, - u8 *bytes, size_t size); -int netxen_rom_fast_write_words(struct netxen_adapter *adapter, int addr, - u8 *bytes, size_t size); -int netxen_flash_unlock(struct netxen_adapter *adapter); -int netxen_backup_crbinit(struct netxen_adapter *adapter); -int netxen_flash_erase_secondary(struct netxen_adapter *adapter); -int netxen_flash_erase_primary(struct netxen_adapter *adapter); - int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data); int netxen_rom_se(struct netxen_adapter *adapter, int addr); int netxen_do_rom_se(struct netxen_adapter *adapter, int addr); diff --git a/trunk/drivers/net/netxen/netxen_nic_ethtool.c b/trunk/drivers/net/netxen/netxen_nic_ethtool.c index cc0efe213e01..c381d77a7336 100644 --- a/trunk/drivers/net/netxen/netxen_nic_ethtool.c +++ b/trunk/drivers/net/netxen/netxen_nic_ethtool.c @@ -32,7 +32,6 @@ */ #include -#include #include #include #include @@ -95,7 +94,17 @@ static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = { static int netxen_nic_get_eeprom_len(struct net_device *dev) { - return FLASH_TOTAL_SIZE; + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + int n; + + if ((netxen_rom_fast_read(adapter, 0, &n) == 0) + && (n & NETXEN_ROM_ROUNDUP)) { + n &= ~NETXEN_ROM_ROUNDUP; + if (n < NETXEN_MAX_EEPROM_LEN) + return n; + } + return 0; } static void @@ -431,92 +440,18 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, struct netxen_port *port = netdev_priv(dev); struct netxen_adapter *adapter = port->adapter; int offset; - int ret; if (eeprom->len == 0) return -EINVAL; eeprom->magic = (port->pdev)->vendor | ((port->pdev)->device << 16); - offset = eeprom->offset; - - ret = netxen_rom_fast_read_words(adapter, offset, bytes, - eeprom->len); - if (ret < 0) - return ret; - + for (offset = 0; offset < eeprom->len; offset++) + if (netxen_rom_fast_read + (adapter, (8 * offset) + 8, (int *)eeprom->data) == -1) + return -EIO; return 0; } -static int -netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, - u8 * bytes) -{ - struct netxen_port *port = netdev_priv(dev); - struct netxen_adapter *adapter = port->adapter; - int offset = eeprom->offset; - static int flash_start; - static int ready_to_flash; - int ret; - - if (flash_start == 0) { - ret = netxen_flash_unlock(adapter); - if (ret < 0) { - printk(KERN_ERR "%s: Flash unlock failed.\n", - netxen_nic_driver_name); - return ret; - } - printk(KERN_INFO "%s: flash unlocked. \n", - netxen_nic_driver_name); - ret = netxen_flash_erase_secondary(adapter); - if (ret != FLASH_SUCCESS) { - printk(KERN_ERR "%s: Flash erase failed.\n", - netxen_nic_driver_name); - return ret; - } - printk(KERN_INFO "%s: secondary flash erased successfully.\n", - netxen_nic_driver_name); - flash_start = 1; - return 0; - } - - if (offset == BOOTLD_START) { - ret = netxen_flash_erase_primary(adapter); - if (ret != FLASH_SUCCESS) { - printk(KERN_ERR "%s: Flash erase failed.\n", - netxen_nic_driver_name); - return ret; - } - - ret = netxen_rom_se(adapter, USER_START); - if (ret != FLASH_SUCCESS) - return ret; - ret = netxen_rom_se(adapter, FIXED_START); - if (ret != FLASH_SUCCESS) - return ret; - - printk(KERN_INFO "%s: primary flash erased successfully\n", - netxen_nic_driver_name); - - ret = netxen_backup_crbinit(adapter); - if (ret != FLASH_SUCCESS) { - printk(KERN_ERR "%s: CRBinit backup failed.\n", - netxen_nic_driver_name); - return ret; - } - printk(KERN_INFO "%s: CRBinit backup done.\n", - netxen_nic_driver_name); - ready_to_flash = 1; - } - - if (!ready_to_flash) { - printk(KERN_ERR "%s: Invalid write sequence, returning...\n", - netxen_nic_driver_name); - return -EINVAL; - } - - return netxen_rom_fast_write_words(adapter, offset, bytes, eeprom->len); -} - static void netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) { @@ -786,7 +721,6 @@ struct ethtool_ops netxen_nic_ethtool_ops = { .get_link = netxen_nic_get_link, .get_eeprom_len = netxen_nic_get_eeprom_len, .get_eeprom = netxen_nic_get_eeprom, - .set_eeprom = netxen_nic_set_eeprom, .get_ringparam = netxen_nic_get_ringparam, .get_pauseparam = netxen_nic_get_pauseparam, .set_pauseparam = netxen_nic_set_pauseparam, diff --git a/trunk/drivers/net/netxen/netxen_nic_init.c b/trunk/drivers/net/netxen/netxen_nic_init.c index f7bb8c90537c..973af96337a9 100644 --- a/trunk/drivers/net/netxen/netxen_nic_init.c +++ b/trunk/drivers/net/netxen/netxen_nic_init.c @@ -110,7 +110,6 @@ static void crb_addr_transform_setup(void) crb_addr_transform(CAM); crb_addr_transform(C2C1); crb_addr_transform(C2C0); - crb_addr_transform(SMB); } int netxen_init_firmware(struct netxen_adapter *adapter) @@ -277,7 +276,6 @@ unsigned long netxen_decode_crb_addr(unsigned long addr) static long rom_max_timeout = 10000; static long rom_lock_timeout = 1000000; -static long rom_write_timeout = 700; static inline int rom_lock(struct netxen_adapter *adapter) { @@ -406,7 +404,7 @@ do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); - udelay(70); /* prevent bursting on CRB */ + udelay(100); /* prevent bursting on CRB */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); if (netxen_wait_rom_done(adapter)) { @@ -415,46 +413,13 @@ do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) } /* reset abyte_cnt and dummy_byte_cnt */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); - udelay(70); /* prevent bursting on CRB */ + udelay(100); /* prevent bursting on CRB */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); return 0; } -static inline int -do_rom_fast_read_words(struct netxen_adapter *adapter, int addr, - u8 *bytes, size_t size) -{ - int addridx; - int ret = 0; - - for (addridx = addr; addridx < (addr + size); addridx += 4) { - ret = do_rom_fast_read(adapter, addridx, (int *)bytes); - if (ret != 0) - break; - bytes += 4; - } - - return ret; -} - -int -netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, - u8 *bytes, size_t size) -{ - int ret; - - ret = rom_lock(adapter); - if (ret < 0) - return ret; - - ret = do_rom_fast_read_words(adapter, addr, bytes, size); - - netxen_rom_unlock(adapter); - return ret; -} - int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { int ret; @@ -478,152 +443,6 @@ int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data) netxen_rom_unlock(adapter); return ret; } - -static inline int do_rom_fast_write_words(struct netxen_adapter *adapter, - int addr, u8 *bytes, size_t size) -{ - int addridx = addr; - int ret = 0; - - while (addridx < (addr + size)) { - int last_attempt = 0; - int timeout = 0; - int data; - - data = *(u32*)bytes; - - ret = do_rom_fast_write(adapter, addridx, data); - if (ret < 0) - return ret; - - while(1) { - int data1; - - do_rom_fast_read(adapter, addridx, &data1); - if (data1 == data) - break; - - if (timeout++ >= rom_write_timeout) { - if (last_attempt++ < 4) { - ret = do_rom_fast_write(adapter, - addridx, data); - if (ret < 0) - return ret; - } - else { - printk(KERN_INFO "Data write did not " - "succeed at address 0x%x\n", addridx); - break; - } - } - } - - bytes += 4; - addridx += 4; - } - - return ret; -} - -int netxen_rom_fast_write_words(struct netxen_adapter *adapter, int addr, - u8 *bytes, size_t size) -{ - int ret = 0; - - ret = rom_lock(adapter); - if (ret < 0) - return ret; - - ret = do_rom_fast_write_words(adapter, addr, bytes, size); - netxen_rom_unlock(adapter); - - return ret; -} - -int netxen_rom_wrsr(struct netxen_adapter *adapter, int data) -{ - int ret; - - ret = netxen_rom_wren(adapter); - if (ret < 0) - return ret; - - netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_ROM_WDATA, data); - netxen_crb_writelit_adapter(adapter, - NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0x1); - - ret = netxen_wait_rom_done(adapter); - if (ret < 0) - return ret; - - return netxen_rom_wip_poll(adapter); -} - -int netxen_rom_rdsr(struct netxen_adapter *adapter) -{ - int ret; - - ret = rom_lock(adapter); - if (ret < 0) - return ret; - - ret = netxen_do_rom_rdsr(adapter); - netxen_rom_unlock(adapter); - return ret; -} - -int netxen_backup_crbinit(struct netxen_adapter *adapter) -{ - int ret = FLASH_SUCCESS; - int val; - char *buffer = kmalloc(FLASH_SECTOR_SIZE, GFP_KERNEL); - - if (!buffer) - return -ENOMEM; - /* unlock sector 63 */ - val = netxen_rom_rdsr(adapter); - val = val & 0xe3; - ret = netxen_rom_wrsr(adapter, val); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - ret = netxen_rom_wip_poll(adapter); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - /* copy sector 0 to sector 63 */ - ret = netxen_rom_fast_read_words(adapter, CRBINIT_START, - buffer, FLASH_SECTOR_SIZE); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - ret = netxen_rom_fast_write_words(adapter, FIXED_START, - buffer, FLASH_SECTOR_SIZE); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - /* lock sector 63 */ - val = netxen_rom_rdsr(adapter); - if (!(val & 0x8)) { - val |= (0x1 << 2); - /* lock sector 63 */ - if (netxen_rom_wrsr(adapter, val) == 0) { - ret = netxen_rom_wip_poll(adapter); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - /* lock SR writes */ - ret = netxen_rom_wip_poll(adapter); - if (ret != FLASH_SUCCESS) - goto out_kfree; - } - } - -out_kfree: - kfree(buffer); - return ret; -} - int netxen_do_rom_se(struct netxen_adapter *adapter, int addr) { netxen_rom_wren(adapter); @@ -638,27 +457,6 @@ int netxen_do_rom_se(struct netxen_adapter *adapter, int addr) return netxen_rom_wip_poll(adapter); } -void check_erased_flash(struct netxen_adapter *adapter, int addr) -{ - int i; - int val; - int count = 0, erased_errors = 0; - int range; - - range = (addr == USER_START) ? FIXED_START : addr + FLASH_SECTOR_SIZE; - - for (i = addr; i < range; i += 4) { - netxen_rom_fast_read(adapter, i, &val); - if (val != 0xffffffff) - erased_errors++; - count++; - } - - if (erased_errors) - printk(KERN_INFO "0x%x out of 0x%x words fail to be erased " - "for sector address: %x\n", erased_errors, count, addr); -} - int netxen_rom_se(struct netxen_adapter *adapter, int addr) { int ret = 0; @@ -667,68 +465,6 @@ int netxen_rom_se(struct netxen_adapter *adapter, int addr) } ret = netxen_do_rom_se(adapter, addr); netxen_rom_unlock(adapter); - msleep(30); - check_erased_flash(adapter, addr); - - return ret; -} - -int -netxen_flash_erase_sections(struct netxen_adapter *adapter, int start, int end) -{ - int ret = FLASH_SUCCESS; - int i; - - for (i = start; i < end; i++) { - ret = netxen_rom_se(adapter, i * FLASH_SECTOR_SIZE); - if (ret) - break; - ret = netxen_rom_wip_poll(adapter); - if (ret < 0) - return ret; - } - - return ret; -} - -int -netxen_flash_erase_secondary(struct netxen_adapter *adapter) -{ - int ret = FLASH_SUCCESS; - int start, end; - - start = SECONDARY_START / FLASH_SECTOR_SIZE; - end = USER_START / FLASH_SECTOR_SIZE; - ret = netxen_flash_erase_sections(adapter, start, end); - - return ret; -} - -int -netxen_flash_erase_primary(struct netxen_adapter *adapter) -{ - int ret = FLASH_SUCCESS; - int start, end; - - start = PRIMARY_START / FLASH_SECTOR_SIZE; - end = SECONDARY_START / FLASH_SECTOR_SIZE; - ret = netxen_flash_erase_sections(adapter, start, end); - - return ret; -} - -int netxen_flash_unlock(struct netxen_adapter *adapter) -{ - int ret = 0; - - ret = netxen_rom_wrsr(adapter, 0); - if (ret < 0) - return ret; - - ret = netxen_rom_wren(adapter); - if (ret < 0) - return ret; - return ret; } @@ -807,13 +543,9 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) } for (i = 0; i < n; i++) { - off = netxen_decode_crb_addr((unsigned long)buf[i].addr); - if (off == NETXEN_ADDR_ERROR) { - printk(KERN_ERR"CRB init value out of range %lx\n", - buf[i].addr); - continue; - } - off += NETXEN_PCI_CRBSPACE; + off = + netxen_decode_crb_addr((unsigned long)buf[i].addr) + + NETXEN_PCI_CRBSPACE; /* skipping cold reboot MAGIC */ if (off == NETXEN_CAM_RAM(0x1fc)) continue; @@ -930,7 +662,6 @@ void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) int loops = 0; if (!pegtune_val) { - val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); while (val != PHAN_INITIALIZE_COMPLETE && loops < 200000) { udelay(100); schedule(); diff --git a/trunk/drivers/net/oaknet.c b/trunk/drivers/net/oaknet.c new file mode 100644 index 000000000000..702e3e95612a --- /dev/null +++ b/trunk/drivers/net/oaknet.c @@ -0,0 +1,666 @@ +/* + * + * Copyright (c) 1999-2000 Grant Erickson + * + * Module name: oaknet.c + * + * Description: + * Driver for the National Semiconductor DP83902AV Ethernet controller + * on-board the IBM PowerPC "Oak" evaluation board. Adapted from the + * various other 8390 drivers written by Donald Becker and Paul Gortmaker. + * + * Additional inspiration from the "tcd8390.c" driver from TiVo, Inc. + * and "enetLib.c" from IBM. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "8390.h" + + +/* Preprocessor Defines */ + +#if !defined(TRUE) || TRUE != 1 +#define TRUE 1 +#endif + +#if !defined(FALSE) || FALSE != 0 +#define FALSE 0 +#endif + +#define OAKNET_START_PG 0x20 /* First page of TX buffer */ +#define OAKNET_STOP_PG 0x40 /* Last pagge +1 of RX ring */ + +#define OAKNET_WAIT (2 * HZ / 100) /* 20 ms */ + +/* Experimenting with some fixes for a broken driver... */ + +#define OAKNET_DISINT +#define OAKNET_HEADCHECK +#define OAKNET_RWFIX + + +/* Global Variables */ + +static const char *name = "National DP83902AV"; + +static struct net_device *oaknet_devs; + + +/* Function Prototypes */ + +static int oaknet_open(struct net_device *dev); +static int oaknet_close(struct net_device *dev); + +static void oaknet_reset_8390(struct net_device *dev); +static void oaknet_get_8390_hdr(struct net_device *dev, + struct e8390_pkt_hdr *hdr, int ring_page); +static void oaknet_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset); +static void oaknet_block_output(struct net_device *dev, int count, + const unsigned char *buf, int start_page); + +static void oaknet_dma_error(struct net_device *dev, const char *name); + + +/* + * int oaknet_init() + * + * Description: + * This routine performs all the necessary platform-specific initiali- + * zation and set-up for the IBM "Oak" evaluation board's National + * Semiconductor DP83902AV "ST-NIC" Ethernet controller. + * + * Input(s): + * N/A + * + * Output(s): + * N/A + * + * Returns: + * 0 if OK, otherwise system error number on error. + * + */ +static int __init oaknet_init(void) +{ + register int i; + int reg0, regd; + int ret = -ENOMEM; + struct net_device *dev; +#if 0 + unsigned long ioaddr = OAKNET_IO_BASE; +#else + unsigned long ioaddr = ioremap(OAKNET_IO_BASE, OAKNET_IO_SIZE); +#endif + bd_t *bip = (bd_t *)__res; + + if (!ioaddr) + return -ENOMEM; + + dev = alloc_ei_netdev(); + if (!dev) + goto out_unmap; + + ret = -EBUSY; + if (!request_region(OAKNET_IO_BASE, OAKNET_IO_SIZE, name)) + goto out_dev; + + /* Quick register check to see if the device is really there. */ + + ret = -ENODEV; + if ((reg0 = ei_ibp(ioaddr)) == 0xFF) + goto out_region; + + /* + * That worked. Now a more thorough check, using the multicast + * address registers, that the device is definitely out there + * and semi-functional. + */ + + ei_obp(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD); + regd = ei_ibp(ioaddr + 0x0D); + ei_obp(0xFF, ioaddr + 0x0D); + ei_obp(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD); + ei_ibp(ioaddr + EN0_COUNTER0); + + /* It's no good. Fix things back up and leave. */ + + ret = -ENODEV; + if (ei_ibp(ioaddr + EN0_COUNTER0) != 0) { + ei_obp(reg0, ioaddr); + ei_obp(regd, ioaddr + 0x0D); + goto out_region; + } + + SET_MODULE_OWNER(dev); + + /* + * This controller is on an embedded board, so the base address + * and interrupt assignments are pre-assigned and unchageable. + */ + + dev->base_addr = ioaddr; + dev->irq = OAKNET_INT; + + /* + * Disable all chip interrupts for now and ACK all pending + * interrupts. + */ + + ei_obp(0x0, ioaddr + EN0_IMR); + ei_obp(0xFF, ioaddr + EN0_ISR); + + /* Attempt to get the interrupt line */ + + ret = -EAGAIN; + if (request_irq(dev->irq, ei_interrupt, 0, name, dev)) { + printk("%s: unable to request interrupt %d.\n", + name, dev->irq); + goto out_region; + } + + /* Tell the world about what and where we've found. */ + + printk("%s: %s at", dev->name, name); + for (i = 0; i < ETHER_ADDR_LEN; ++i) { + dev->dev_addr[i] = bip->bi_enetaddr[i]; + printk("%c%.2x", (i ? ':' : ' '), dev->dev_addr[i]); + } + printk(", found at %#lx, using IRQ %d.\n", dev->base_addr, dev->irq); + + /* Set up some required driver fields and then we're done. */ + + ei_status.name = name; + ei_status.word16 = FALSE; + ei_status.tx_start_page = OAKNET_START_PG; + ei_status.rx_start_page = OAKNET_START_PG + TX_PAGES; + ei_status.stop_page = OAKNET_STOP_PG; + + ei_status.reset_8390 = &oaknet_reset_8390; + ei_status.block_input = &oaknet_block_input; + ei_status.block_output = &oaknet_block_output; + ei_status.get_8390_hdr = &oaknet_get_8390_hdr; + + dev->open = oaknet_open; + dev->stop = oaknet_close; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = ei_poll; +#endif + + NS8390_init(dev, FALSE); + ret = register_netdev(dev); + if (ret) + goto out_irq; + + oaknet_devs = dev; + return 0; + +out_irq; + free_irq(dev->irq, dev); +out_region: + release_region(OAKNET_IO_BASE, OAKNET_IO_SIZE); +out_dev: + free_netdev(dev); +out_unmap: + iounmap(ioaddr); + return ret; +} + +/* + * static int oaknet_open() + * + * Description: + * This routine is a modest wrapper around ei_open, the 8390-generic, + * driver open routine. This just increments the module usage count + * and passes along the status from ei_open. + * + * Input(s): + * *dev - Pointer to the device structure for this driver. + * + * Output(s): + * *dev - Pointer to the device structure for this driver, potentially + * modified by ei_open. + * + * Returns: + * 0 if OK, otherwise < 0 on error. + * + */ +static int +oaknet_open(struct net_device *dev) +{ + int status = ei_open(dev); + return (status); +} + +/* + * static int oaknet_close() + * + * Description: + * This routine is a modest wrapper around ei_close, the 8390-generic, + * driver close routine. This just decrements the module usage count + * and passes along the status from ei_close. + * + * Input(s): + * *dev - Pointer to the device structure for this driver. + * + * Output(s): + * *dev - Pointer to the device structure for this driver, potentially + * modified by ei_close. + * + * Returns: + * 0 if OK, otherwise < 0 on error. + * + */ +static int +oaknet_close(struct net_device *dev) +{ + int status = ei_close(dev); + return (status); +} + +/* + * static void oaknet_reset_8390() + * + * Description: + * This routine resets the DP83902 chip. + * + * Input(s): + * *dev - Pointer to the device structure for this driver. + * + * Output(s): + * N/A + * + * Returns: + * N/A + * + */ +static void +oaknet_reset_8390(struct net_device *dev) +{ + int base = E8390_BASE; + + /* + * We have no provision of reseting the controller as is done + * in other drivers, such as "ne.c". However, the following + * seems to work well enough in the TiVo driver. + */ + + printk("Resetting %s...\n", dev->name); + ei_obp(E8390_STOP | E8390_NODMA | E8390_PAGE0, base + E8390_CMD); + ei_status.txing = 0; + ei_status.dmaing = 0; +} + +/* + * static void oaknet_get_8390_hdr() + * + * Description: + * This routine grabs the 8390-specific header. It's similar to the + * block input routine, but we don't need to be concerned with ring wrap + * as the header will be at the start of a page, so we optimize accordingly. + * + * Input(s): + * *dev - Pointer to the device structure for this driver. + * *hdr - Pointer to storage for the 8390-specific packet header. + * ring_page - ? + * + * Output(s): + * *hdr - Pointer to the 8390-specific packet header for the just- + * received frame. + * + * Returns: + * N/A + * + */ +static void +oaknet_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, + int ring_page) +{ + int base = dev->base_addr; + + /* + * This should NOT happen. If it does, it is the LAST thing you'll + * see. + */ + + if (ei_status.dmaing) { + oaknet_dma_error(dev, "oaknet_get_8390_hdr"); + return; + } + + ei_status.dmaing |= 0x01; + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, base + OAKNET_CMD); + outb_p(sizeof(struct e8390_pkt_hdr), base + EN0_RCNTLO); + outb_p(0, base + EN0_RCNTHI); + outb_p(0, base + EN0_RSARLO); /* On page boundary */ + outb_p(ring_page, base + EN0_RSARHI); + outb_p(E8390_RREAD + E8390_START, base + OAKNET_CMD); + + if (ei_status.word16) + insw(base + OAKNET_DATA, hdr, + sizeof(struct e8390_pkt_hdr) >> 1); + else + insb(base + OAKNET_DATA, hdr, + sizeof(struct e8390_pkt_hdr)); + + /* Byte-swap the packet byte count */ + + hdr->count = le16_to_cpu(hdr->count); + + outb_p(ENISR_RDC, base + EN0_ISR); /* ACK Remote DMA interrupt */ + ei_status.dmaing &= ~0x01; +} + +/* + * XXX - Document me. + */ +static void +oaknet_block_input(struct net_device *dev, int count, struct sk_buff *skb, + int ring_offset) +{ + int base = OAKNET_BASE; + char *buf = skb->data; + + /* + * This should NOT happen. If it does, it is the LAST thing you'll + * see. + */ + + if (ei_status.dmaing) { + oaknet_dma_error(dev, "oaknet_block_input"); + return; + } + +#ifdef OAKNET_DISINT + save_flags(flags); + cli(); +#endif + + ei_status.dmaing |= 0x01; + ei_obp(E8390_NODMA + E8390_PAGE0 + E8390_START, base + E8390_CMD); + ei_obp(count & 0xff, base + EN0_RCNTLO); + ei_obp(count >> 8, base + EN0_RCNTHI); + ei_obp(ring_offset & 0xff, base + EN0_RSARLO); + ei_obp(ring_offset >> 8, base + EN0_RSARHI); + ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD); + if (ei_status.word16) { + ei_isw(base + E8390_DATA, buf, count >> 1); + if (count & 0x01) { + buf[count - 1] = ei_ib(base + E8390_DATA); +#ifdef OAKNET_HEADCHECK + bytes++; +#endif + } + } else { + ei_isb(base + E8390_DATA, buf, count); + } +#ifdef OAKNET_HEADCHECK + /* + * This was for the ALPHA version only, but enough people have + * been encountering problems so it is still here. If you see + * this message you either 1) have a slightly incompatible clone + * or 2) have noise/speed problems with your bus. + */ + + /* DMA termination address check... */ + { + int addr, tries = 20; + do { + /* DON'T check for 'ei_ibp(EN0_ISR) & ENISR_RDC' here + -- it's broken for Rx on some cards! */ + int high = ei_ibp(base + EN0_RSARHI); + int low = ei_ibp(base + EN0_RSARLO); + addr = (high << 8) + low; + if (((ring_offset + bytes) & 0xff) == low) + break; + } while (--tries > 0); + if (tries <= 0) + printk("%s: RX transfer address mismatch," + "%#4.4x (expected) vs. %#4.4x (actual).\n", + dev->name, ring_offset + bytes, addr); + } +#endif + ei_obp(ENISR_RDC, base + EN0_ISR); /* ACK Remote DMA interrupt */ + ei_status.dmaing &= ~0x01; + +#ifdef OAKNET_DISINT + restore_flags(flags); +#endif +} + +/* + * static void oaknet_block_output() + * + * Description: + * This routine... + * + * Input(s): + * *dev - Pointer to the device structure for this driver. + * count - Number of bytes to be transferred. + * *buf - + * start_page - + * + * Output(s): + * N/A + * + * Returns: + * N/A + * + */ +static void +oaknet_block_output(struct net_device *dev, int count, + const unsigned char *buf, int start_page) +{ + int base = E8390_BASE; +#if 0 + int bug; +#endif + unsigned long start; +#ifdef OAKNET_DISINT + unsigned long flags; +#endif +#ifdef OAKNET_HEADCHECK + int retries = 0; +#endif + + /* Round the count up for word writes. */ + + if (ei_status.word16 && (count & 0x1)) + count++; + + /* + * This should NOT happen. If it does, it is the LAST thing you'll + * see. + */ + + if (ei_status.dmaing) { + oaknet_dma_error(dev, "oaknet_block_output"); + return; + } + +#ifdef OAKNET_DISINT + save_flags(flags); + cli(); +#endif + + ei_status.dmaing |= 0x01; + + /* Make sure we are in page 0. */ + + ei_obp(E8390_PAGE0 + E8390_START + E8390_NODMA, base + E8390_CMD); + +#ifdef OAKNET_HEADCHECK +retry: +#endif + +#if 0 + /* + * The 83902 documentation states that the processor needs to + * do a "dummy read" before doing the remote write to work + * around a chip bug they don't feel like fixing. + */ + + bug = 0; + while (1) { + unsigned int rdhi; + unsigned int rdlo; + + /* Now the normal output. */ + ei_obp(ENISR_RDC, base + EN0_ISR); + ei_obp(count & 0xff, base + EN0_RCNTLO); + ei_obp(count >> 8, base + EN0_RCNTHI); + ei_obp(0x00, base + EN0_RSARLO); + ei_obp(start_page, base + EN0_RSARHI); + + if (bug++) + break; + + /* Perform the dummy read */ + rdhi = ei_ibp(base + EN0_CRDAHI); + rdlo = ei_ibp(base + EN0_CRDALO); + ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD); + + while (1) { + unsigned int nrdhi; + unsigned int nrdlo; + nrdhi = ei_ibp(base + EN0_CRDAHI); + nrdlo = ei_ibp(base + EN0_CRDALO); + if ((rdhi != nrdhi) || (rdlo != nrdlo)) + break; + } + } +#else +#ifdef OAKNET_RWFIX + /* + * Handle the read-before-write bug the same way as the + * Crynwr packet driver -- the Nat'l Semi. method doesn't work. + * Actually this doesn't always work either, but if you have + * problems with your 83902 this is better than nothing! + */ + + ei_obp(0x42, base + EN0_RCNTLO); + ei_obp(0x00, base + EN0_RCNTHI); + ei_obp(0x42, base + EN0_RSARLO); + ei_obp(0x00, base + EN0_RSARHI); + ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD); + /* Make certain that the dummy read has occurred. */ + udelay(6); +#endif + + ei_obp(ENISR_RDC, base + EN0_ISR); + + /* Now the normal output. */ + ei_obp(count & 0xff, base + EN0_RCNTLO); + ei_obp(count >> 8, base + EN0_RCNTHI); + ei_obp(0x00, base + EN0_RSARLO); + ei_obp(start_page, base + EN0_RSARHI); +#endif /* 0/1 */ + + ei_obp(E8390_RWRITE + E8390_START, base + E8390_CMD); + if (ei_status.word16) { + ei_osw(E8390_BASE + E8390_DATA, buf, count >> 1); + } else { + ei_osb(E8390_BASE + E8390_DATA, buf, count); + } + +#ifdef OAKNET_DISINT + restore_flags(flags); +#endif + + start = jiffies; + +#ifdef OAKNET_HEADCHECK + /* + * This was for the ALPHA version only, but enough people have + * been encountering problems so it is still here. + */ + + { + /* DMA termination address check... */ + int addr, tries = 20; + do { + int high = ei_ibp(base + EN0_RSARHI); + int low = ei_ibp(base + EN0_RSARLO); + addr = (high << 8) + low; + if ((start_page << 8) + count == addr) + break; + } while (--tries > 0); + + if (tries <= 0) { + printk("%s: Tx packet transfer address mismatch," + "%#4.4x (expected) vs. %#4.4x (actual).\n", + dev->name, (start_page << 8) + count, addr); + if (retries++ == 0) + goto retry; + } + } +#endif + + while ((ei_ibp(base + EN0_ISR) & ENISR_RDC) == 0) { + if (time_after(jiffies, start + OAKNET_WAIT)) { + printk("%s: timeout waiting for Tx RDC.\n", dev->name); + oaknet_reset_8390(dev); + NS8390_init(dev, TRUE); + break; + } + } + + ei_obp(ENISR_RDC, base + EN0_ISR); /* Ack intr. */ + ei_status.dmaing &= ~0x01; +} + +/* + * static void oaknet_dma_error() + * + * Description: + * This routine prints out a last-ditch informative message to the console + * indicating that a DMA error occurred. If you see this, it's the last + * thing you'll see. + * + * Input(s): + * *dev - Pointer to the device structure for this driver. + * *name - Informative text (e.g. function name) indicating where the + * DMA error occurred. + * + * Output(s): + * N/A + * + * Returns: + * N/A + * + */ +static void +oaknet_dma_error(struct net_device *dev, const char *name) +{ + printk(KERN_EMERG "%s: DMAing conflict in %s." + "[DMAstat:%d][irqlock:%d][intr:%ld]\n", + dev->name, name, ei_status.dmaing, ei_status.irqlock, + dev->interrupt); +} + +/* + * Oak Ethernet module unload interface. + */ +static void __exit oaknet_cleanup_module (void) +{ + /* Convert to loop once driver supports multiple devices. */ + unregister_netdev(oaknet_dev); + free_irq(oaknet_devs->irq, oaknet_devs); + release_region(oaknet_devs->base_addr, OAKNET_IO_SIZE); + iounmap(ioaddr); + free_netdev(oaknet_devs); +} + +module_init(oaknet_init); +module_exit(oaknet_cleanup_module); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/pasemi_mac.c b/trunk/drivers/net/pasemi_mac.c deleted file mode 100644 index d670ac74824f..000000000000 --- a/trunk/drivers/net/pasemi_mac.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* - * Copyright (C) 2006-2007 PA Semi, Inc - * - * Driver for the PA Semi PWRficient onchip 1G/10G Ethernet MACs - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "pasemi_mac.h" - - -/* TODO list - * - * - Get rid of pci_{read,write}_config(), map registers with ioremap - * for performance - * - PHY support - * - Multicast support - * - Large MTU support - * - Other performance improvements - */ - - -/* Must be a power of two */ -#define RX_RING_SIZE 512 -#define TX_RING_SIZE 512 - -#define TX_DESC(mac, num) ((mac)->tx->desc[(num) & (TX_RING_SIZE-1)]) -#define TX_DESC_INFO(mac, num) ((mac)->tx->desc_info[(num) & (TX_RING_SIZE-1)]) -#define RX_DESC(mac, num) ((mac)->rx->desc[(num) & (RX_RING_SIZE-1)]) -#define RX_DESC_INFO(mac, num) ((mac)->rx->desc_info[(num) & (RX_RING_SIZE-1)]) -#define RX_BUFF(mac, num) ((mac)->rx->buffers[(num) & (RX_RING_SIZE-1)]) - -#define BUF_SIZE 1646 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ - -/* XXXOJN these should come out of the device tree some day */ -#define PAS_DMA_CAP_BASE 0xe00d0040 -#define PAS_DMA_CAP_SIZE 0x100 -#define PAS_DMA_COM_BASE 0xe00d0100 -#define PAS_DMA_COM_SIZE 0x100 - -static struct pasdma_status *dma_status; - -static int pasemi_get_mac_addr(struct pasemi_mac *mac) -{ - struct pci_dev *pdev = mac->pdev; - struct device_node *dn = pci_device_to_OF_node(pdev); - const u8 *maddr; - u8 addr[6]; - - if (!dn) { - dev_dbg(&pdev->dev, - "No device node for mac, not configuring\n"); - return -ENOENT; - } - - maddr = get_property(dn, "mac-address", NULL); - if (maddr == NULL) { - dev_warn(&pdev->dev, - "no mac address in device tree, not configuring\n"); - return -ENOENT; - } - - if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0], - &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) { - dev_warn(&pdev->dev, - "can't parse mac address, not configuring\n"); - return -EINVAL; - } - - memcpy(mac->mac_addr, addr, sizeof(addr)); - return 0; -} - -static int pasemi_mac_setup_rx_resources(struct net_device *dev) -{ - struct pasemi_mac_rxring *ring; - struct pasemi_mac *mac = netdev_priv(dev); - int chan_id = mac->dma_rxch; - - ring = kzalloc(sizeof(*ring), GFP_KERNEL); - - if (!ring) - goto out_ring; - - spin_lock_init(&ring->lock); - - ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) * - RX_RING_SIZE, GFP_KERNEL); - - if (!ring->desc_info) - goto out_desc_info; - - /* Allocate descriptors */ - ring->desc = dma_alloc_coherent(&mac->dma_pdev->dev, - RX_RING_SIZE * - sizeof(struct pas_dma_xct_descr), - &ring->dma, GFP_KERNEL); - - if (!ring->desc) - goto out_desc; - - memset(ring->desc, 0, RX_RING_SIZE * sizeof(struct pas_dma_xct_descr)); - - ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev, - RX_RING_SIZE * sizeof(u64), - &ring->buf_dma, GFP_KERNEL); - if (!ring->buffers) - goto out_buffers; - - memset(ring->buffers, 0, RX_RING_SIZE * sizeof(u64)); - - pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXCHAN_BASEL(chan_id), - PAS_DMA_RXCHAN_BASEL_BRBL(ring->dma)); - - pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXCHAN_BASEU(chan_id), - PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) | - PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 2)); - - pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXCHAN_CFG(chan_id), - PAS_DMA_RXCHAN_CFG_HBU(1)); - - pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXINT_BASEL(mac->dma_if), - PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers))); - - pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXINT_BASEU(mac->dma_if), - PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) | - PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3)); - - ring->next_to_fill = 0; - ring->next_to_clean = 0; - - snprintf(ring->irq_name, sizeof(ring->irq_name), - "%s rx", dev->name); - mac->rx = ring; - - return 0; - -out_buffers: - dma_free_coherent(&mac->dma_pdev->dev, - RX_RING_SIZE * sizeof(struct pas_dma_xct_descr), - mac->rx->desc, mac->rx->dma); -out_desc: - kfree(ring->desc_info); -out_desc_info: - kfree(ring); -out_ring: - return -ENOMEM; -} - - -static int pasemi_mac_setup_tx_resources(struct net_device *dev) -{ - struct pasemi_mac *mac = netdev_priv(dev); - u32 val; - int chan_id = mac->dma_txch; - struct pasemi_mac_txring *ring; - - ring = kzalloc(sizeof(*ring), GFP_KERNEL); - if (!ring) - goto out_ring; - - spin_lock_init(&ring->lock); - - ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) * - TX_RING_SIZE, GFP_KERNEL); - if (!ring->desc_info) - goto out_desc_info; - - /* Allocate descriptors */ - ring->desc = dma_alloc_coherent(&mac->dma_pdev->dev, - TX_RING_SIZE * - sizeof(struct pas_dma_xct_descr), - &ring->dma, GFP_KERNEL); - if (!ring->desc) - goto out_desc; - - memset(ring->desc, 0, TX_RING_SIZE * sizeof(struct pas_dma_xct_descr)); - - pci_write_config_dword(mac->dma_pdev, PAS_DMA_TXCHAN_BASEL(chan_id), - PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma)); - val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->dma >> 32); - val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 2); - - pci_write_config_dword(mac->dma_pdev, PAS_DMA_TXCHAN_BASEU(chan_id), val); - - pci_write_config_dword(mac->dma_pdev, PAS_DMA_TXCHAN_CFG(chan_id), - PAS_DMA_TXCHAN_CFG_TY_IFACE | - PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) | - PAS_DMA_TXCHAN_CFG_UP | - PAS_DMA_TXCHAN_CFG_WT(2)); - - ring->next_to_use = 0; - ring->next_to_clean = 0; - - snprintf(ring->irq_name, sizeof(ring->irq_name), - "%s tx", dev->name); - mac->tx = ring; - - return 0; - -out_desc: - kfree(ring->desc_info); -out_desc_info: - kfree(ring); -out_ring: - return -ENOMEM; -} - -static void pasemi_mac_free_tx_resources(struct net_device *dev) -{ - struct pasemi_mac *mac = netdev_priv(dev); - unsigned int i; - struct pasemi_mac_buffer *info; - struct pas_dma_xct_descr *dp; - - for (i = 0; i < TX_RING_SIZE; i++) { - info = &TX_DESC_INFO(mac, i); - dp = &TX_DESC(mac, i); - if (info->dma) { - if (info->skb) { - pci_unmap_single(mac->dma_pdev, - info->dma, - info->skb->len, - PCI_DMA_TODEVICE); - dev_kfree_skb_any(info->skb); - } - info->dma = 0; - info->skb = NULL; - dp->mactx = 0; - dp->ptr = 0; - } - } - - dma_free_coherent(&mac->dma_pdev->dev, - TX_RING_SIZE * sizeof(struct pas_dma_xct_descr), - mac->tx->desc, mac->tx->dma); - - kfree(mac->tx->desc_info); - kfree(mac->tx); - mac->tx = NULL; -} - -static void pasemi_mac_free_rx_resources(struct net_device *dev) -{ - struct pasemi_mac *mac = netdev_priv(dev); - unsigned int i; - struct pasemi_mac_buffer *info; - struct pas_dma_xct_descr *dp; - - for (i = 0; i < RX_RING_SIZE; i++) { - info = &RX_DESC_INFO(mac, i); - dp = &RX_DESC(mac, i); - if (info->dma) { - if (info->skb) { - pci_unmap_single(mac->dma_pdev, - info->dma, - info->skb->len, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(info->skb); - } - info->dma = 0; - info->skb = NULL; - dp->macrx = 0; - dp->ptr = 0; - } - } - - dma_free_coherent(&mac->dma_pdev->dev, - RX_RING_SIZE * sizeof(struct pas_dma_xct_descr), - mac->rx->desc, mac->rx->dma); - - dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64), - mac->rx->buffers, mac->rx->buf_dma); - - kfree(mac->rx->desc_info); - kfree(mac->rx); - mac->rx = NULL; -} - -static void pasemi_mac_replenish_rx_ring(struct net_device *dev) -{ - struct pasemi_mac *mac = netdev_priv(dev); - unsigned int i; - int start = mac->rx->next_to_fill; - unsigned int count; - - count = (mac->rx->next_to_clean + RX_RING_SIZE - - mac->rx->next_to_fill) & (RX_RING_SIZE - 1); - - /* Check to see if we're doing first-time setup */ - if (unlikely(mac->rx->next_to_clean == 0 && mac->rx->next_to_fill == 0)) - count = RX_RING_SIZE; - - if (count <= 0) - return; - - for (i = start; i < start + count; i++) { - struct pasemi_mac_buffer *info = &RX_DESC_INFO(mac, i); - u64 *buff = &RX_BUFF(mac, i); - struct sk_buff *skb; - dma_addr_t dma; - - skb = dev_alloc_skb(BUF_SIZE); - - if (!skb) { - count = i - start; - break; - } - - skb->dev = dev; - - dma = pci_map_single(mac->dma_pdev, skb->data, skb->len, - PCI_DMA_FROMDEVICE); - - if (dma_mapping_error(dma)) { - dev_kfree_skb_irq(info->skb); - count = i - start; - break; - } - - info->skb = skb; - info->dma = dma; - *buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma); - } - - wmb(); - - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_RXCHAN_INCR(mac->dma_rxch), - count); - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_RXINT_INCR(mac->dma_if), - count); - - mac->rx->next_to_fill += count; -} - -static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit) -{ - unsigned int i; - int start, count; - - spin_lock(&mac->rx->lock); - - start = mac->rx->next_to_clean; - count = 0; - - for (i = start; i < (start + RX_RING_SIZE) && count < limit; i++) { - struct pas_dma_xct_descr *dp; - struct pasemi_mac_buffer *info; - struct sk_buff *skb; - unsigned int j, len; - dma_addr_t dma; - - rmb(); - - dp = &RX_DESC(mac, i); - - if (!(dp->macrx & XCT_MACRX_O)) - break; - - count++; - - info = NULL; - - /* We have to scan for our skb since there's no way - * to back-map them from the descriptor, and if we - * have several receive channels then they might not - * show up in the same order as they were put on the - * interface ring. - */ - - dma = (dp->ptr & XCT_PTR_ADDR_M); - for (j = start; j < (start + RX_RING_SIZE); j++) { - info = &RX_DESC_INFO(mac, j); - if (info->dma == dma) - break; - } - - BUG_ON(!info); - BUG_ON(info->dma != dma); - - pci_unmap_single(mac->dma_pdev, info->dma, info->skb->len, - PCI_DMA_FROMDEVICE); - - skb = info->skb; - - len = (dp->macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S; - - skb_put(skb, len); - - skb->protocol = eth_type_trans(skb, mac->netdev); - - if ((dp->macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK) { - skb->ip_summed = CHECKSUM_COMPLETE; - skb->csum = (dp->macrx & XCT_MACRX_CSUM_M) >> - XCT_MACRX_CSUM_S; - } else - skb->ip_summed = CHECKSUM_NONE; - - mac->stats.rx_bytes += len; - mac->stats.rx_packets++; - - netif_receive_skb(skb); - - info->dma = 0; - info->skb = NULL; - dp->ptr = 0; - dp->macrx = 0; - } - - mac->rx->next_to_clean += count; - pasemi_mac_replenish_rx_ring(mac->netdev); - - spin_unlock(&mac->rx->lock); - - return count; -} - -static int pasemi_mac_clean_tx(struct pasemi_mac *mac) -{ - int i; - struct pasemi_mac_buffer *info; - struct pas_dma_xct_descr *dp; - int start, count; - int flags; - - spin_lock_irqsave(&mac->tx->lock, flags); - - start = mac->tx->next_to_clean; - count = 0; - - for (i = start; i < mac->tx->next_to_use; i++) { - dp = &TX_DESC(mac, i); - if (!dp || (dp->mactx & XCT_MACTX_O)) - break; - - count++; - - info = &TX_DESC_INFO(mac, i); - - pci_unmap_single(mac->dma_pdev, info->dma, - info->skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(info->skb); - - info->skb = NULL; - info->dma = 0; - dp->mactx = 0; - dp->ptr = 0; - } - mac->tx->next_to_clean += count; - spin_unlock_irqrestore(&mac->tx->lock, flags); - - return count; -} - - -static irqreturn_t pasemi_mac_rx_intr(int irq, void *data) -{ - struct net_device *dev = data; - struct pasemi_mac *mac = netdev_priv(dev); - unsigned int reg; - - if (!(*mac->rx_status & PAS_STATUS_INT)) - return IRQ_NONE; - - netif_rx_schedule(dev); - pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG, - PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0)); - - reg = PAS_IOB_DMA_RXCH_RESET_PINTC | PAS_IOB_DMA_RXCH_RESET_SINTC | - PAS_IOB_DMA_RXCH_RESET_DINTC; - if (*mac->rx_status & PAS_STATUS_TIMER) - reg |= PAS_IOB_DMA_RXCH_RESET_TINTC; - - pci_write_config_dword(mac->iob_pdev, - PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg); - - - return IRQ_HANDLED; -} - -static irqreturn_t pasemi_mac_tx_intr(int irq, void *data) -{ - struct net_device *dev = data; - struct pasemi_mac *mac = netdev_priv(dev); - unsigned int reg; - int was_full; - - was_full = mac->tx->next_to_clean - mac->tx->next_to_use == TX_RING_SIZE; - - if (!(*mac->tx_status & PAS_STATUS_INT)) - return IRQ_NONE; - - pasemi_mac_clean_tx(mac); - - reg = PAS_IOB_DMA_TXCH_RESET_PINTC | PAS_IOB_DMA_TXCH_RESET_SINTC; - if (*mac->tx_status & PAS_STATUS_TIMER) - reg |= PAS_IOB_DMA_TXCH_RESET_TINTC; - - pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), - reg); - - if (was_full) - netif_wake_queue(dev); - - return IRQ_HANDLED; -} - -static int pasemi_mac_open(struct net_device *dev) -{ - struct pasemi_mac *mac = netdev_priv(dev); - unsigned int flags; - int ret; - - /* enable rx section */ - pci_write_config_dword(mac->dma_pdev, PAS_DMA_COM_RXCMD, - PAS_DMA_COM_RXCMD_EN); - - /* enable tx section */ - pci_write_config_dword(mac->dma_pdev, PAS_DMA_COM_TXCMD, - PAS_DMA_COM_TXCMD_EN); - - flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) | - PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) | - PAS_MAC_CFG_TXP_TIFT(8) | PAS_MAC_CFG_TXP_TIFG(12); - - pci_write_config_dword(mac->pdev, PAS_MAC_CFG_TXP, flags); - - flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE | - PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE; - - flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G; - - pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch), - PAS_IOB_DMA_RXCH_CFG_CNTTH(30)); - - pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG, - PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(1000000)); - - pci_write_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, flags); - - ret = pasemi_mac_setup_rx_resources(dev); - if (ret) - goto out_rx_resources; - - ret = pasemi_mac_setup_tx_resources(dev); - if (ret) - goto out_tx_resources; - - pci_write_config_dword(mac->pdev, PAS_MAC_IPC_CHNL, - PAS_MAC_IPC_CHNL_DCHNO(mac->dma_rxch) | - PAS_MAC_IPC_CHNL_BCH(mac->dma_rxch)); - - /* enable rx if */ - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_RXINT_RCMDSTA(mac->dma_if), - PAS_DMA_RXINT_RCMDSTA_EN); - - /* enable rx channel */ - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), - PAS_DMA_RXCHAN_CCMDSTA_EN | - PAS_DMA_RXCHAN_CCMDSTA_DU); - - /* enable tx channel */ - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), - PAS_DMA_TXCHAN_TCMDSTA_EN); - - pasemi_mac_replenish_rx_ring(dev); - - netif_start_queue(dev); - netif_poll_enable(dev); - - ret = request_irq(mac->dma_pdev->irq + mac->dma_txch, - &pasemi_mac_tx_intr, IRQF_DISABLED, - mac->tx->irq_name, dev); - if (ret) { - dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n", - mac->dma_pdev->irq + mac->dma_txch, ret); - goto out_tx_int; - } - - ret = request_irq(mac->dma_pdev->irq + 20 + mac->dma_rxch, - &pasemi_mac_rx_intr, IRQF_DISABLED, - mac->rx->irq_name, dev); - if (ret) { - dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n", - mac->dma_pdev->irq + 20 + mac->dma_rxch, ret); - goto out_rx_int; - } - - return 0; - -out_rx_int: - free_irq(mac->dma_pdev->irq + mac->dma_txch, dev); -out_tx_int: - netif_poll_disable(dev); - netif_stop_queue(dev); - pasemi_mac_free_tx_resources(dev); -out_tx_resources: - pasemi_mac_free_rx_resources(dev); -out_rx_resources: - - return ret; -} - -#define MAX_RETRIES 5000 - -static int pasemi_mac_close(struct net_device *dev) -{ - struct pasemi_mac *mac = netdev_priv(dev); - unsigned int stat; - int retries; - - netif_stop_queue(dev); - - /* Clean out any pending buffers */ - pasemi_mac_clean_tx(mac); - pasemi_mac_clean_rx(mac, RX_RING_SIZE); - - /* Disable interface */ - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), - PAS_DMA_TXCHAN_TCMDSTA_ST); - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_RXINT_RCMDSTA(mac->dma_if), - PAS_DMA_RXINT_RCMDSTA_ST); - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), - PAS_DMA_RXCHAN_CCMDSTA_ST); - - for (retries = 0; retries < MAX_RETRIES; retries++) { - pci_read_config_dword(mac->dma_pdev, - PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), - &stat); - if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT) - break; - cond_resched(); - } - - if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)) { - dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n"); - } - - for (retries = 0; retries < MAX_RETRIES; retries++) { - pci_read_config_dword(mac->dma_pdev, - PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), - &stat); - if (stat & PAS_DMA_RXCHAN_CCMDSTA_ACT) - break; - cond_resched(); - } - - if (!(stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)) { - dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n"); - } - - for (retries = 0; retries < MAX_RETRIES; retries++) { - pci_read_config_dword(mac->dma_pdev, - PAS_DMA_RXINT_RCMDSTA(mac->dma_if), - &stat); - if (stat & PAS_DMA_RXINT_RCMDSTA_ACT) - break; - cond_resched(); - } - - if (!(stat & PAS_DMA_RXINT_RCMDSTA_ACT)) { - dev_err(&mac->dma_pdev->dev, "Failed to stop rx interface\n"); - } - - /* Then, disable the channel. This must be done separately from - * stopping, since you can't disable when active. - */ - - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), 0); - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), 0); - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0); - - free_irq(mac->dma_pdev->irq + mac->dma_txch, dev); - free_irq(mac->dma_pdev->irq + 20 + mac->dma_rxch, dev); - - /* Free resources */ - pasemi_mac_free_rx_resources(dev); - pasemi_mac_free_tx_resources(dev); - - return 0; -} - -static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) -{ - struct pasemi_mac *mac = netdev_priv(dev); - struct pasemi_mac_txring *txring; - struct pasemi_mac_buffer *info; - struct pas_dma_xct_descr *dp; - u64 dflags; - dma_addr_t map; - int flags; - - dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_SS | XCT_MACTX_CRC_PAD; - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - switch (skb->nh.iph->protocol) { - case IPPROTO_TCP: - dflags |= XCT_MACTX_CSUM_TCP; - dflags |= XCT_MACTX_IPH((skb->h.raw - skb->nh.raw) >> 2); - dflags |= XCT_MACTX_IPO(skb->nh.raw - skb->data); - break; - case IPPROTO_UDP: - dflags |= XCT_MACTX_CSUM_UDP; - dflags |= XCT_MACTX_IPH((skb->h.raw - skb->nh.raw) >> 2); - dflags |= XCT_MACTX_IPO(skb->nh.raw - skb->data); - break; - } - } - - map = pci_map_single(mac->dma_pdev, skb->data, skb->len, PCI_DMA_TODEVICE); - - if (dma_mapping_error(map)) - return NETDEV_TX_BUSY; - - txring = mac->tx; - - spin_lock_irqsave(&txring->lock, flags); - - if (txring->next_to_clean - txring->next_to_use == TX_RING_SIZE) { - spin_unlock_irqrestore(&txring->lock, flags); - pasemi_mac_clean_tx(mac); - spin_lock_irqsave(&txring->lock, flags); - - if (txring->next_to_clean - txring->next_to_use == - TX_RING_SIZE) { - /* Still no room -- stop the queue and wait for tx - * intr when there's room. - */ - netif_stop_queue(dev); - goto out_err; - } - } - - - dp = &TX_DESC(mac, txring->next_to_use); - info = &TX_DESC_INFO(mac, txring->next_to_use); - - dp->mactx = dflags | XCT_MACTX_LLEN(skb->len); - dp->ptr = XCT_PTR_LEN(skb->len) | XCT_PTR_ADDR(map); - info->dma = map; - info->skb = skb; - - txring->next_to_use++; - mac->stats.tx_packets++; - mac->stats.tx_bytes += skb->len; - - spin_unlock_irqrestore(&txring->lock, flags); - - pci_write_config_dword(mac->dma_pdev, - PAS_DMA_TXCHAN_INCR(mac->dma_txch), 1); - - return NETDEV_TX_OK; - -out_err: - spin_unlock_irqrestore(&txring->lock, flags); - pci_unmap_single(mac->dma_pdev, map, skb->len, PCI_DMA_TODEVICE); - return NETDEV_TX_BUSY; -} - -static struct net_device_stats *pasemi_mac_get_stats(struct net_device *dev) -{ - struct pasemi_mac *mac = netdev_priv(dev); - - return &mac->stats; -} - -static void pasemi_mac_set_rx_mode(struct net_device *dev) -{ - struct pasemi_mac *mac = netdev_priv(dev); - unsigned int flags; - - pci_read_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, &flags); - - /* Set promiscuous */ - if (dev->flags & IFF_PROMISC) - flags |= PAS_MAC_CFG_PCFG_PR; - else - flags &= ~PAS_MAC_CFG_PCFG_PR; - - pci_write_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, flags); -} - - -static int pasemi_mac_poll(struct net_device *dev, int *budget) -{ - int pkts, limit = min(*budget, dev->quota); - struct pasemi_mac *mac = netdev_priv(dev); - - pkts = pasemi_mac_clean_rx(mac, limit); - - if (pkts < limit) { - /* all done, no more packets present */ - netif_rx_complete(dev); - - /* re-enable receive interrupts */ - pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG, - PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(1000000)); - return 0; - } else { - /* used up our quantum, so reschedule */ - dev->quota -= pkts; - *budget -= pkts; - return 1; - } -} - -static int __devinit -pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - static int index = 0; - struct net_device *dev; - struct pasemi_mac *mac; - int err; - - err = pci_enable_device(pdev); - if (err) - return err; - - dev = alloc_etherdev(sizeof(struct pasemi_mac)); - if (dev == NULL) { - dev_err(&pdev->dev, - "pasemi_mac: Could not allocate ethernet device.\n"); - err = -ENOMEM; - goto out_disable_device; - } - - SET_MODULE_OWNER(dev); - pci_set_drvdata(pdev, dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - mac = netdev_priv(dev); - - mac->pdev = pdev; - mac->netdev = dev; - mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL); - - if (!mac->dma_pdev) { - dev_err(&pdev->dev, "Can't find DMA Controller\n"); - err = -ENODEV; - goto out_free_netdev; - } - - mac->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL); - - if (!mac->iob_pdev) { - dev_err(&pdev->dev, "Can't find I/O Bridge\n"); - err = -ENODEV; - goto out_put_dma_pdev; - } - - /* These should come out of the device tree eventually */ - mac->dma_txch = index; - mac->dma_rxch = index; - - /* We probe GMAC before XAUI, but the DMA interfaces are - * in XAUI, GMAC order. - */ - if (index < 4) - mac->dma_if = index + 2; - else - mac->dma_if = index - 4; - index++; - - switch (pdev->device) { - case 0xa005: - mac->type = MAC_TYPE_GMAC; - break; - case 0xa006: - mac->type = MAC_TYPE_XAUI; - break; - default: - err = -ENODEV; - goto out; - } - - /* get mac addr from device tree */ - if (pasemi_get_mac_addr(mac) || !is_valid_ether_addr(mac->mac_addr)) { - err = -ENODEV; - goto out; - } - memcpy(dev->dev_addr, mac->mac_addr, sizeof(mac->mac_addr)); - - dev->open = pasemi_mac_open; - dev->stop = pasemi_mac_close; - dev->hard_start_xmit = pasemi_mac_start_tx; - dev->get_stats = pasemi_mac_get_stats; - dev->set_multicast_list = pasemi_mac_set_rx_mode; - dev->weight = 64; - dev->poll = pasemi_mac_poll; - dev->features = NETIF_F_HW_CSUM; - - /* The dma status structure is located in the I/O bridge, and - * is cache coherent. - */ - if (!dma_status) - /* XXXOJN This should come from the device tree */ - dma_status = __ioremap(0xfd800000, 0x1000, 0); - - mac->rx_status = &dma_status->rx_sta[mac->dma_rxch]; - mac->tx_status = &dma_status->tx_sta[mac->dma_txch]; - - err = register_netdev(dev); - - if (err) { - dev_err(&mac->pdev->dev, "register_netdev failed with error %d\n", - err); - goto out; - } else - printk(KERN_INFO "%s: PA Semi %s: intf %d, txch %d, rxch %d, " - "hw addr %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI", - mac->dma_if, mac->dma_txch, mac->dma_rxch, - dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - - return err; - -out: - pci_dev_put(mac->iob_pdev); -out_put_dma_pdev: - pci_dev_put(mac->dma_pdev); -out_free_netdev: - free_netdev(dev); -out_disable_device: - pci_disable_device(pdev); - return err; - -} - -static void __devexit pasemi_mac_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct pasemi_mac *mac; - - if (!netdev) - return; - - mac = netdev_priv(netdev); - - unregister_netdev(netdev); - - pci_disable_device(pdev); - pci_dev_put(mac->dma_pdev); - pci_dev_put(mac->iob_pdev); - - pci_set_drvdata(pdev, NULL); - free_netdev(netdev); -} - -static struct pci_device_id pasemi_mac_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) }, - { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) }, -}; - -MODULE_DEVICE_TABLE(pci, pasemi_mac_pci_tbl); - -static struct pci_driver pasemi_mac_driver = { - .name = "pasemi_mac", - .id_table = pasemi_mac_pci_tbl, - .probe = pasemi_mac_probe, - .remove = __devexit_p(pasemi_mac_remove), -}; - -static void __exit pasemi_mac_cleanup_module(void) -{ - pci_unregister_driver(&pasemi_mac_driver); - __iounmap(dma_status); - dma_status = NULL; -} - -int pasemi_mac_init_module(void) -{ - return pci_register_driver(&pasemi_mac_driver); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Olof Johansson "); -MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver"); - -module_init(pasemi_mac_init_module); -module_exit(pasemi_mac_cleanup_module); diff --git a/trunk/drivers/net/pasemi_mac.h b/trunk/drivers/net/pasemi_mac.h deleted file mode 100644 index c3e37e46a18a..000000000000 --- a/trunk/drivers/net/pasemi_mac.h +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (C) 2006 PA Semi, Inc - * - * Driver for the PA6T-1682M onchip 1G/10G Ethernet MACs, soft state and - * hardware register layouts. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 PASEMI_MAC_H -#define PASEMI_MAC_H - -#include -#include -#include - -struct pasemi_mac_txring { - spinlock_t lock; - struct pas_dma_xct_descr *desc; - dma_addr_t dma; - unsigned int size; - unsigned int next_to_use; - unsigned int next_to_clean; - struct pasemi_mac_buffer *desc_info; - char irq_name[10]; /* "eth%d tx" */ -}; - -struct pasemi_mac_rxring { - spinlock_t lock; - struct pas_dma_xct_descr *desc; /* RX channel descriptor ring */ - dma_addr_t dma; - u64 *buffers; /* RX interface buffer ring */ - dma_addr_t buf_dma; - unsigned int size; - unsigned int next_to_fill; - unsigned int next_to_clean; - struct pasemi_mac_buffer *desc_info; - char irq_name[10]; /* "eth%d rx" */ -}; - -struct pasemi_mac { - struct net_device *netdev; - struct pci_dev *pdev; - struct pci_dev *dma_pdev; - struct pci_dev *iob_pdev; - struct net_device_stats stats; - - /* Pointer to the cacheable per-channel status registers */ - u64 *rx_status; - u64 *tx_status; - - u8 type; -#define MAC_TYPE_GMAC 1 -#define MAC_TYPE_XAUI 2 - u32 dma_txch; - u32 dma_if; - u32 dma_rxch; - - u8 mac_addr[6]; - - struct timer_list rxtimer; - - struct pasemi_mac_txring *tx; - struct pasemi_mac_rxring *rx; -}; - -/* Software status descriptor (desc_info) */ -struct pasemi_mac_buffer { - struct sk_buff *skb; - dma_addr_t dma; -}; - - -/* status register layout in IOB region, at 0xfb800000 */ -struct pasdma_status { - u64 rx_sta[64]; - u64 tx_sta[20]; -}; - -/* descriptor structure */ -struct pas_dma_xct_descr { - union { - u64 mactx; - u64 macrx; - }; - union { - u64 ptr; - u64 rxb; - }; -}; - -/* MAC CFG register offsets */ - -enum { - PAS_MAC_CFG_PCFG = 0x80, - PAS_MAC_CFG_TXP = 0x98, - PAS_MAC_IPC_CHNL = 0x208, -}; - -/* MAC CFG register fields */ -#define PAS_MAC_CFG_PCFG_PE 0x80000000 -#define PAS_MAC_CFG_PCFG_CE 0x40000000 -#define PAS_MAC_CFG_PCFG_BU 0x20000000 -#define PAS_MAC_CFG_PCFG_TT 0x10000000 -#define PAS_MAC_CFG_PCFG_TSR_M 0x0c000000 -#define PAS_MAC_CFG_PCFG_TSR_10M 0x00000000 -#define PAS_MAC_CFG_PCFG_TSR_100M 0x04000000 -#define PAS_MAC_CFG_PCFG_TSR_1G 0x08000000 -#define PAS_MAC_CFG_PCFG_TSR_10G 0x0c000000 -#define PAS_MAC_CFG_PCFG_T24 0x02000000 -#define PAS_MAC_CFG_PCFG_PR 0x01000000 -#define PAS_MAC_CFG_PCFG_CRO_M 0x00ff0000 -#define PAS_MAC_CFG_PCFG_CRO_S 16 -#define PAS_MAC_CFG_PCFG_IPO_M 0x0000ff00 -#define PAS_MAC_CFG_PCFG_IPO_S 8 -#define PAS_MAC_CFG_PCFG_S1 0x00000080 -#define PAS_MAC_CFG_PCFG_IO_M 0x00000060 -#define PAS_MAC_CFG_PCFG_IO_MAC 0x00000000 -#define PAS_MAC_CFG_PCFG_IO_OFF 0x00000020 -#define PAS_MAC_CFG_PCFG_IO_IND_ETH 0x00000040 -#define PAS_MAC_CFG_PCFG_IO_IND_IP 0x00000060 -#define PAS_MAC_CFG_PCFG_LP 0x00000010 -#define PAS_MAC_CFG_PCFG_TS 0x00000008 -#define PAS_MAC_CFG_PCFG_HD 0x00000004 -#define PAS_MAC_CFG_PCFG_SPD_M 0x00000003 -#define PAS_MAC_CFG_PCFG_SPD_10M 0x00000000 -#define PAS_MAC_CFG_PCFG_SPD_100M 0x00000001 -#define PAS_MAC_CFG_PCFG_SPD_1G 0x00000002 -#define PAS_MAC_CFG_PCFG_SPD_10G 0x00000003 -#define PAS_MAC_CFG_TXP_FCF 0x01000000 -#define PAS_MAC_CFG_TXP_FCE 0x00800000 -#define PAS_MAC_CFG_TXP_FC 0x00400000 -#define PAS_MAC_CFG_TXP_FPC_M 0x00300000 -#define PAS_MAC_CFG_TXP_FPC_S 20 -#define PAS_MAC_CFG_TXP_FPC(x) (((x) << PAS_MAC_CFG_TXP_FPC_S) & \ - PAS_MAC_CFG_TXP_FPC_M) -#define PAS_MAC_CFG_TXP_RT 0x00080000 -#define PAS_MAC_CFG_TXP_BL 0x00040000 -#define PAS_MAC_CFG_TXP_SL_M 0x00030000 -#define PAS_MAC_CFG_TXP_SL_S 16 -#define PAS_MAC_CFG_TXP_SL(x) (((x) << PAS_MAC_CFG_TXP_SL_S) & \ - PAS_MAC_CFG_TXP_SL_M) -#define PAS_MAC_CFG_TXP_COB_M 0x0000f000 -#define PAS_MAC_CFG_TXP_COB_S 12 -#define PAS_MAC_CFG_TXP_COB(x) (((x) << PAS_MAC_CFG_TXP_COB_S) & \ - PAS_MAC_CFG_TXP_COB_M) -#define PAS_MAC_CFG_TXP_TIFT_M 0x00000f00 -#define PAS_MAC_CFG_TXP_TIFT_S 8 -#define PAS_MAC_CFG_TXP_TIFT(x) (((x) << PAS_MAC_CFG_TXP_TIFT_S) & \ - PAS_MAC_CFG_TXP_TIFT_M) -#define PAS_MAC_CFG_TXP_TIFG_M 0x000000ff -#define PAS_MAC_CFG_TXP_TIFG_S 0 -#define PAS_MAC_CFG_TXP_TIFG(x) (((x) << PAS_MAC_CFG_TXP_TIFG_S) & \ - PAS_MAC_CFG_TXP_TIFG_M) - -#define PAS_MAC_IPC_CHNL_DCHNO_M 0x003f0000 -#define PAS_MAC_IPC_CHNL_DCHNO_S 16 -#define PAS_MAC_IPC_CHNL_DCHNO(x) (((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \ - PAS_MAC_IPC_CHNL_DCHNO_M) -#define PAS_MAC_IPC_CHNL_BCH_M 0x0000003f -#define PAS_MAC_IPC_CHNL_BCH_S 0 -#define PAS_MAC_IPC_CHNL_BCH(x) (((x) << PAS_MAC_IPC_CHNL_BCH_S) & \ - PAS_MAC_IPC_CHNL_BCH_M) - -/* All these registers live in the PCI configuration space for the DMA PCI - * device. Use the normal PCI config access functions for them. - */ -enum { - PAS_DMA_COM_TXCMD = 0x100, /* Transmit Command Register */ - PAS_DMA_COM_TXSTA = 0x104, /* Transmit Status Register */ - PAS_DMA_COM_RXCMD = 0x108, /* Receive Command Register */ - PAS_DMA_COM_RXSTA = 0x10c, /* Receive Status Register */ -}; -#define PAS_DMA_COM_TXCMD_EN 0x00000001 /* enable */ -#define PAS_DMA_COM_TXSTA_ACT 0x00000001 /* active */ -#define PAS_DMA_COM_RXCMD_EN 0x00000001 /* enable */ -#define PAS_DMA_COM_RXSTA_ACT 0x00000001 /* active */ - - -/* Per-interface and per-channel registers */ -#define _PAS_DMA_RXINT_STRIDE 0x20 -#define PAS_DMA_RXINT_RCMDSTA(i) (0x200+(i)*_PAS_DMA_RXINT_STRIDE) -#define PAS_DMA_RXINT_RCMDSTA_EN 0x00000001 -#define PAS_DMA_RXINT_RCMDSTA_ST 0x00000002 -#define PAS_DMA_RXINT_RCMDSTA_OO 0x00000100 -#define PAS_DMA_RXINT_RCMDSTA_BP 0x00000200 -#define PAS_DMA_RXINT_RCMDSTA_DR 0x00000400 -#define PAS_DMA_RXINT_RCMDSTA_BT 0x00000800 -#define PAS_DMA_RXINT_RCMDSTA_TB 0x00001000 -#define PAS_DMA_RXINT_RCMDSTA_ACT 0x00010000 -#define PAS_DMA_RXINT_RCMDSTA_DROPS_M 0xfffe0000 -#define PAS_DMA_RXINT_RCMDSTA_DROPS_S 17 -#define PAS_DMA_RXINT_INCR(i) (0x210+(i)*_PAS_DMA_RXINT_STRIDE) -#define PAS_DMA_RXINT_INCR_INCR_M 0x0000ffff -#define PAS_DMA_RXINT_INCR_INCR_S 0 -#define PAS_DMA_RXINT_INCR_INCR(x) ((x) & 0x0000ffff) -#define PAS_DMA_RXINT_BASEL(i) (0x218+(i)*_PAS_DMA_RXINT_STRIDE) -#define PAS_DMA_RXINT_BASEL_BRBL(x) ((x) & ~0x3f) -#define PAS_DMA_RXINT_BASEU(i) (0x21c+(i)*_PAS_DMA_RXINT_STRIDE) -#define PAS_DMA_RXINT_BASEU_BRBH(x) ((x) & 0xfff) -#define PAS_DMA_RXINT_BASEU_SIZ_M 0x3fff0000 /* # of cache lines worth of buffer ring */ -#define PAS_DMA_RXINT_BASEU_SIZ_S 16 /* 0 = 16K */ -#define PAS_DMA_RXINT_BASEU_SIZ(x) (((x) << PAS_DMA_RXINT_BASEU_SIZ_S) & \ - PAS_DMA_RXINT_BASEU_SIZ_M) - - -#define _PAS_DMA_TXCHAN_STRIDE 0x20 /* Size per channel */ -#define _PAS_DMA_TXCHAN_TCMDSTA 0x300 /* Command / Status */ -#define _PAS_DMA_TXCHAN_CFG 0x304 /* Configuration */ -#define _PAS_DMA_TXCHAN_DSCRBU 0x308 /* Descriptor BU Allocation */ -#define _PAS_DMA_TXCHAN_INCR 0x310 /* Descriptor increment */ -#define _PAS_DMA_TXCHAN_CNT 0x314 /* Descriptor count/offset */ -#define _PAS_DMA_TXCHAN_BASEL 0x318 /* Descriptor ring base (low) */ -#define _PAS_DMA_TXCHAN_BASEU 0x31c /* (high) */ -#define PAS_DMA_TXCHAN_TCMDSTA(c) (0x300+(c)*_PAS_DMA_TXCHAN_STRIDE) -#define PAS_DMA_TXCHAN_TCMDSTA_EN 0x00000001 /* Enabled */ -#define PAS_DMA_TXCHAN_TCMDSTA_ST 0x00000002 /* Stop interface */ -#define PAS_DMA_TXCHAN_TCMDSTA_ACT 0x00010000 /* Active */ -#define PAS_DMA_TXCHAN_CFG(c) (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE) -#define PAS_DMA_TXCHAN_CFG_TY_IFACE 0x00000000 /* Type = interface */ -#define PAS_DMA_TXCHAN_CFG_TATTR_M 0x0000003c -#define PAS_DMA_TXCHAN_CFG_TATTR_S 2 -#define PAS_DMA_TXCHAN_CFG_TATTR(x) (((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \ - PAS_DMA_TXCHAN_CFG_TATTR_M) -#define PAS_DMA_TXCHAN_CFG_WT_M 0x000001c0 -#define PAS_DMA_TXCHAN_CFG_WT_S 6 -#define PAS_DMA_TXCHAN_CFG_WT(x) (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \ - PAS_DMA_TXCHAN_CFG_WT_M) -#define PAS_DMA_TXCHAN_CFG_CF 0x00001000 /* Clean first line */ -#define PAS_DMA_TXCHAN_CFG_CL 0x00002000 /* Clean last line */ -#define PAS_DMA_TXCHAN_CFG_UP 0x00004000 /* update tx descr when sent */ -#define PAS_DMA_TXCHAN_INCR(c) (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE) -#define PAS_DMA_TXCHAN_BASEL(c) (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE) -#define PAS_DMA_TXCHAN_BASEL_BRBL_M 0xffffffc0 -#define PAS_DMA_TXCHAN_BASEL_BRBL_S 0 -#define PAS_DMA_TXCHAN_BASEL_BRBL(x) (((x) << PAS_DMA_TXCHAN_BASEL_BRBL_S) & \ - PAS_DMA_TXCHAN_BASEL_BRBL_M) -#define PAS_DMA_TXCHAN_BASEU(c) (0x31c+(c)*_PAS_DMA_TXCHAN_STRIDE) -#define PAS_DMA_TXCHAN_BASEU_BRBH_M 0x00000fff -#define PAS_DMA_TXCHAN_BASEU_BRBH_S 0 -#define PAS_DMA_TXCHAN_BASEU_BRBH(x) (((x) << PAS_DMA_TXCHAN_BASEU_BRBH_S) & \ - PAS_DMA_TXCHAN_BASEU_BRBH_M) -/* # of cache lines worth of buffer ring */ -#define PAS_DMA_TXCHAN_BASEU_SIZ_M 0x3fff0000 -#define PAS_DMA_TXCHAN_BASEU_SIZ_S 16 /* 0 = 16K */ -#define PAS_DMA_TXCHAN_BASEU_SIZ(x) (((x) << PAS_DMA_TXCHAN_BASEU_SIZ_S) & \ - PAS_DMA_TXCHAN_BASEU_SIZ_M) - -#define _PAS_DMA_RXCHAN_STRIDE 0x20 /* Size per channel */ -#define _PAS_DMA_RXCHAN_CCMDSTA 0x800 /* Command / Status */ -#define _PAS_DMA_RXCHAN_CFG 0x804 /* Configuration */ -#define _PAS_DMA_RXCHAN_INCR 0x810 /* Descriptor increment */ -#define _PAS_DMA_RXCHAN_CNT 0x814 /* Descriptor count/offset */ -#define _PAS_DMA_RXCHAN_BASEL 0x818 /* Descriptor ring base (low) */ -#define _PAS_DMA_RXCHAN_BASEU 0x81c /* (high) */ -#define PAS_DMA_RXCHAN_CCMDSTA(c) (0x800+(c)*_PAS_DMA_RXCHAN_STRIDE) -#define PAS_DMA_RXCHAN_CCMDSTA_EN 0x00000001 /* Enabled */ -#define PAS_DMA_RXCHAN_CCMDSTA_ST 0x00000002 /* Stop interface */ -#define PAS_DMA_RXCHAN_CCMDSTA_ACT 0x00010000 /* Active */ -#define PAS_DMA_RXCHAN_CCMDSTA_DU 0x00020000 -#define PAS_DMA_RXCHAN_CFG(c) (0x804+(c)*_PAS_DMA_RXCHAN_STRIDE) -#define PAS_DMA_RXCHAN_CFG_HBU_M 0x00000380 -#define PAS_DMA_RXCHAN_CFG_HBU_S 7 -#define PAS_DMA_RXCHAN_CFG_HBU(x) (((x) << PAS_DMA_RXCHAN_CFG_HBU_S) & \ - PAS_DMA_RXCHAN_CFG_HBU_M) -#define PAS_DMA_RXCHAN_INCR(c) (0x810+(c)*_PAS_DMA_RXCHAN_STRIDE) -#define PAS_DMA_RXCHAN_BASEL(c) (0x818+(c)*_PAS_DMA_RXCHAN_STRIDE) -#define PAS_DMA_RXCHAN_BASEL_BRBL_M 0xffffffc0 -#define PAS_DMA_RXCHAN_BASEL_BRBL_S 0 -#define PAS_DMA_RXCHAN_BASEL_BRBL(x) (((x) << PAS_DMA_RXCHAN_BASEL_BRBL_S) & \ - PAS_DMA_RXCHAN_BASEL_BRBL_M) -#define PAS_DMA_RXCHAN_BASEU(c) (0x81c+(c)*_PAS_DMA_RXCHAN_STRIDE) -#define PAS_DMA_RXCHAN_BASEU_BRBH_M 0x00000fff -#define PAS_DMA_RXCHAN_BASEU_BRBH_S 0 -#define PAS_DMA_RXCHAN_BASEU_BRBH(x) (((x) << PAS_DMA_RXCHAN_BASEU_BRBH_S) & \ - PAS_DMA_RXCHAN_BASEU_BRBH_M) -/* # of cache lines worth of buffer ring */ -#define PAS_DMA_RXCHAN_BASEU_SIZ_M 0x3fff0000 -#define PAS_DMA_RXCHAN_BASEU_SIZ_S 16 /* 0 = 16K */ -#define PAS_DMA_RXCHAN_BASEU_SIZ(x) (((x) << PAS_DMA_RXCHAN_BASEU_SIZ_S) & \ - PAS_DMA_RXCHAN_BASEU_SIZ_M) - -#define PAS_STATUS_PCNT_M 0x000000000000ffffull -#define PAS_STATUS_PCNT_S 0 -#define PAS_STATUS_DCNT_M 0x00000000ffff0000ull -#define PAS_STATUS_DCNT_S 16 -#define PAS_STATUS_BPCNT_M 0x0000ffff00000000ull -#define PAS_STATUS_BPCNT_S 32 -#define PAS_STATUS_TIMER 0x1000000000000000ull -#define PAS_STATUS_ERROR 0x2000000000000000ull -#define PAS_STATUS_SOFT 0x4000000000000000ull -#define PAS_STATUS_INT 0x8000000000000000ull - -#define PAS_IOB_DMA_RXCH_CFG(i) (0x1100 + (i)*4) -#define PAS_IOB_DMA_RXCH_CFG_CNTTH_M 0x00000fff -#define PAS_IOB_DMA_RXCH_CFG_CNTTH_S 0 -#define PAS_IOB_DMA_RXCH_CFG_CNTTH(x) (((x) << PAS_IOB_DMA_RXCH_CFG_CNTTH_S) & \ - PAS_IOB_DMA_RXCH_CFG_CNTTH_M) -#define PAS_IOB_DMA_TXCH_CFG(i) (0x1200 + (i)*4) -#define PAS_IOB_DMA_TXCH_CFG_CNTTH_M 0x00000fff -#define PAS_IOB_DMA_TXCH_CFG_CNTTH_S 0 -#define PAS_IOB_DMA_TXCH_CFG_CNTTH(x) (((x) << PAS_IOB_DMA_TXCH_CFG_CNTTH_S) & \ - PAS_IOB_DMA_TXCH_CFG_CNTTH_M) -#define PAS_IOB_DMA_RXCH_STAT(i) (0x1300 + (i)*4) -#define PAS_IOB_DMA_RXCH_STAT_INTGEN 0x00001000 -#define PAS_IOB_DMA_RXCH_STAT_CNTDEL_M 0x00000fff -#define PAS_IOB_DMA_RXCH_STAT_CNTDEL_S 0 -#define PAS_IOB_DMA_RXCH_STAT_CNTDEL(x) (((x) << PAS_IOB_DMA_RXCH_STAT_CNTDEL_S) &\ - PAS_IOB_DMA_RXCH_STAT_CNTDEL_M) -#define PAS_IOB_DMA_TXCH_STAT(i) (0x1400 + (i)*4) -#define PAS_IOB_DMA_TXCH_STAT_INTGEN 0x00001000 -#define PAS_IOB_DMA_TXCH_STAT_CNTDEL_M 0x00000fff -#define PAS_IOB_DMA_TXCH_STAT_CNTDEL_S 0 -#define PAS_IOB_DMA_TXCH_STAT_CNTDEL(x) (((x) << PAS_IOB_DMA_TXCH_STAT_CNTDEL_S) &\ - PAS_IOB_DMA_TXCH_STAT_CNTDEL_M) -#define PAS_IOB_DMA_RXCH_RESET(i) (0x1500 + (i)*4) -#define PAS_IOB_DMA_RXCH_RESET_PCNT_M 0xffff0000 -#define PAS_IOB_DMA_RXCH_RESET_PCNT_S 0 -#define PAS_IOB_DMA_RXCH_RESET_PCNT(x) (((x) << PAS_IOB_DMA_RXCH_RESET_PCNT_S) & \ - PAS_IOB_DMA_RXCH_RESET_PCNT_M) -#define PAS_IOB_DMA_RXCH_RESET_PCNTRST 0x00000020 -#define PAS_IOB_DMA_RXCH_RESET_DCNTRST 0x00000010 -#define PAS_IOB_DMA_RXCH_RESET_TINTC 0x00000008 -#define PAS_IOB_DMA_RXCH_RESET_DINTC 0x00000004 -#define PAS_IOB_DMA_RXCH_RESET_SINTC 0x00000002 -#define PAS_IOB_DMA_RXCH_RESET_PINTC 0x00000001 -#define PAS_IOB_DMA_TXCH_RESET(i) (0x1600 + (i)*4) -#define PAS_IOB_DMA_TXCH_RESET_PCNT_M 0xffff0000 -#define PAS_IOB_DMA_TXCH_RESET_PCNT_S 0 -#define PAS_IOB_DMA_TXCH_RESET_PCNT(x) (((x) << PAS_IOB_DMA_TXCH_RESET_PCNT_S) & \ - PAS_IOB_DMA_TXCH_RESET_PCNT_M) -#define PAS_IOB_DMA_TXCH_RESET_PCNTRST 0x00000020 -#define PAS_IOB_DMA_TXCH_RESET_DCNTRST 0x00000010 -#define PAS_IOB_DMA_TXCH_RESET_TINTC 0x00000008 -#define PAS_IOB_DMA_TXCH_RESET_DINTC 0x00000004 -#define PAS_IOB_DMA_TXCH_RESET_SINTC 0x00000002 -#define PAS_IOB_DMA_TXCH_RESET_PINTC 0x00000001 - -#define PAS_IOB_DMA_COM_TIMEOUTCFG 0x1700 -#define PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M 0x00ffffff -#define PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S 0 -#define PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(x) (((x) << PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S) & \ - PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M) - -/* Transmit descriptor fields */ -#define XCT_MACTX_T 0x8000000000000000ull -#define XCT_MACTX_ST 0x4000000000000000ull -#define XCT_MACTX_NORES 0x0000000000000000ull -#define XCT_MACTX_8BRES 0x1000000000000000ull -#define XCT_MACTX_24BRES 0x2000000000000000ull -#define XCT_MACTX_40BRES 0x3000000000000000ull -#define XCT_MACTX_I 0x0800000000000000ull -#define XCT_MACTX_O 0x0400000000000000ull -#define XCT_MACTX_E 0x0200000000000000ull -#define XCT_MACTX_VLAN_M 0x0180000000000000ull -#define XCT_MACTX_VLAN_NOP 0x0000000000000000ull -#define XCT_MACTX_VLAN_REMOVE 0x0080000000000000ull -#define XCT_MACTX_VLAN_INSERT 0x0100000000000000ull -#define XCT_MACTX_VLAN_REPLACE 0x0180000000000000ull -#define XCT_MACTX_CRC_M 0x0060000000000000ull -#define XCT_MACTX_CRC_NOP 0x0000000000000000ull -#define XCT_MACTX_CRC_INSERT 0x0020000000000000ull -#define XCT_MACTX_CRC_PAD 0x0040000000000000ull -#define XCT_MACTX_CRC_REPLACE 0x0060000000000000ull -#define XCT_MACTX_SS 0x0010000000000000ull -#define XCT_MACTX_LLEN_M 0x00007fff00000000ull -#define XCT_MACTX_LLEN_S 32ull -#define XCT_MACTX_LLEN(x) ((((long)(x)) << XCT_MACTX_LLEN_S) & \ - XCT_MACTX_LLEN_M) -#define XCT_MACTX_IPH_M 0x00000000f8000000ull -#define XCT_MACTX_IPH_S 27ull -#define XCT_MACTX_IPH(x) ((((long)(x)) << XCT_MACTX_IPH_S) & \ - XCT_MACTX_IPH_M) -#define XCT_MACTX_IPO_M 0x0000000007c00000ull -#define XCT_MACTX_IPO_S 22ull -#define XCT_MACTX_IPO(x) ((((long)(x)) << XCT_MACTX_IPO_S) & \ - XCT_MACTX_IPO_M) -#define XCT_MACTX_CSUM_M 0x0000000000000060ull -#define XCT_MACTX_CSUM_NOP 0x0000000000000000ull -#define XCT_MACTX_CSUM_TCP 0x0000000000000040ull -#define XCT_MACTX_CSUM_UDP 0x0000000000000060ull -#define XCT_MACTX_V6 0x0000000000000010ull -#define XCT_MACTX_C 0x0000000000000004ull -#define XCT_MACTX_AL2 0x0000000000000002ull - -/* Receive descriptor fields */ -#define XCT_MACRX_T 0x8000000000000000ull -#define XCT_MACRX_ST 0x4000000000000000ull -#define XCT_MACRX_NORES 0x0000000000000000ull -#define XCT_MACRX_8BRES 0x1000000000000000ull -#define XCT_MACRX_24BRES 0x2000000000000000ull -#define XCT_MACRX_40BRES 0x3000000000000000ull -#define XCT_MACRX_O 0x0400000000000000ull -#define XCT_MACRX_E 0x0200000000000000ull -#define XCT_MACRX_FF 0x0100000000000000ull -#define XCT_MACRX_PF 0x0080000000000000ull -#define XCT_MACRX_OB 0x0040000000000000ull -#define XCT_MACRX_OD 0x0020000000000000ull -#define XCT_MACRX_FS 0x0010000000000000ull -#define XCT_MACRX_NB_M 0x000fc00000000000ull -#define XCT_MACRX_NB_S 46ULL -#define XCT_MACRX_NB(x) ((((long)(x)) << XCT_MACRX_NB_S) & \ - XCT_MACRX_NB_M) -#define XCT_MACRX_LLEN_M 0x00003fff00000000ull -#define XCT_MACRX_LLEN_S 32ULL -#define XCT_MACRX_LLEN(x) ((((long)(x)) << XCT_MACRX_LLEN_S) & \ - XCT_MACRX_LLEN_M) -#define XCT_MACRX_CRC 0x0000000080000000ull -#define XCT_MACRX_LEN_M 0x0000000060000000ull -#define XCT_MACRX_LEN_TOOSHORT 0x0000000020000000ull -#define XCT_MACRX_LEN_BELOWMIN 0x0000000040000000ull -#define XCT_MACRX_LEN_TRUNC 0x0000000060000000ull -#define XCT_MACRX_CAST_M 0x0000000018000000ull -#define XCT_MACRX_CAST_UNI 0x0000000000000000ull -#define XCT_MACRX_CAST_MULTI 0x0000000008000000ull -#define XCT_MACRX_CAST_BROAD 0x0000000010000000ull -#define XCT_MACRX_CAST_PAUSE 0x0000000018000000ull -#define XCT_MACRX_VLC_M 0x0000000006000000ull -#define XCT_MACRX_FM 0x0000000001000000ull -#define XCT_MACRX_HTY_M 0x0000000000c00000ull -#define XCT_MACRX_HTY_IPV4_OK 0x0000000000000000ull -#define XCT_MACRX_HTY_IPV6 0x0000000000400000ull -#define XCT_MACRX_HTY_IPV4_BAD 0x0000000000800000ull -#define XCT_MACRX_HTY_NONIP 0x0000000000c00000ull -#define XCT_MACRX_IPP_M 0x00000000003f0000ull -#define XCT_MACRX_IPP_S 16 -#define XCT_MACRX_CSUM_M 0x000000000000ffffull -#define XCT_MACRX_CSUM_S 0 - -#define XCT_PTR_T 0x8000000000000000ull -#define XCT_PTR_LEN_M 0x7ffff00000000000ull -#define XCT_PTR_LEN_S 44 -#define XCT_PTR_LEN(x) ((((long)(x)) << XCT_PTR_LEN_S) & \ - XCT_PTR_LEN_M) -#define XCT_PTR_ADDR_M 0x00000fffffffffffull -#define XCT_PTR_ADDR_S 0 -#define XCT_PTR_ADDR(x) ((((long)(x)) << XCT_PTR_ADDR_S) & \ - XCT_PTR_ADDR_M) - -/* Receive interface buffer fields */ -#define XCT_RXB_LEN_M 0x0ffff00000000000ull -#define XCT_RXB_LEN_S 44 -#define XCT_RXB_LEN(x) ((((long)(x)) << XCT_PTR_LEN_S) & XCT_PTR_LEN_M) -#define XCT_RXB_ADDR_M 0x00000fffffffffffull -#define XCT_RXB_ADDR_S 0 -#define XCT_RXB_ADDR(x) ((((long)(x)) << XCT_PTR_ADDR_S) & XCT_PTR_ADDR_M) - - -#endif /* PASEMI_MAC_H */ diff --git a/trunk/drivers/net/qla3xxx.c b/trunk/drivers/net/qla3xxx.c old mode 100755 new mode 100644 index 2429b274f0b0..8844c20eac2d --- a/trunk/drivers/net/qla3xxx.c +++ b/trunk/drivers/net/qla3xxx.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -64,7 +63,6 @@ MODULE_PARM_DESC(msi, "Turn on Message Signaled Interrupts."); static struct pci_device_id ql3xxx_pci_tbl[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3022_DEVICE_ID)}, - {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3032_DEVICE_ID)}, /* required last entry */ {0,} }; @@ -1477,10 +1475,6 @@ static int ql_mii_setup(struct ql3_adapter *qdev) 2) << 7)) return -1; - if (qdev->device_id == QL3032_DEVICE_ID) - ql_write_page0_reg(qdev, - &port_regs->macMIIMgmtControlReg, 0x0f00000); - /* Divide 125MHz clock by 28 to meet PHY timing requirements */ reg = MAC_MII_CONTROL_CLK_SEL_DIV28; @@ -1712,42 +1706,18 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev, struct ob_mac_iocb_rsp *mac_rsp) { struct ql_tx_buf_cb *tx_cb; - int i; tx_cb = &qdev->tx_buf[mac_rsp->transaction_id]; pci_unmap_single(qdev->pdev, - pci_unmap_addr(&tx_cb->map[0], mapaddr), - pci_unmap_len(&tx_cb->map[0], maplen), - PCI_DMA_TODEVICE); - tx_cb->seg_count--; - if (tx_cb->seg_count) { - for (i = 1; i < tx_cb->seg_count; i++) { - pci_unmap_page(qdev->pdev, - pci_unmap_addr(&tx_cb->map[i], - mapaddr), - pci_unmap_len(&tx_cb->map[i], maplen), - PCI_DMA_TODEVICE); - } - } + pci_unmap_addr(tx_cb, mapaddr), + pci_unmap_len(tx_cb, maplen), PCI_DMA_TODEVICE); + dev_kfree_skb_irq(tx_cb->skb); qdev->stats.tx_packets++; qdev->stats.tx_bytes += tx_cb->skb->len; - dev_kfree_skb_irq(tx_cb->skb); tx_cb->skb = NULL; atomic_inc(&qdev->tx_count); } -/* - * The difference between 3022 and 3032 for inbound completions: - * 3022 uses two buffers per completion. The first buffer contains - * (some) header info, the second the remainder of the headers plus - * the data. For this chip we reserve some space at the top of the - * receive buffer so that the header info in buffer one can be - * prepended to the buffer two. Buffer two is the sent up while - * buffer one is returned to the hardware to be reused. - * 3032 receives all of it's data and headers in one buffer for a - * simpler process. 3032 also supports checksum verification as - * can be seen in ql_process_macip_rx_intr(). - */ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev, struct ib_mac_iocb_rsp *ib_mac_rsp_ptr) { @@ -1770,17 +1740,14 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev, qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset; qdev->small_buf_release_cnt++; - if (qdev->device_id == QL3022_DEVICE_ID) { - /* start of first buffer (3022 only) */ - lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr); - lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index]; - qdev->lrg_buf_release_cnt++; - if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS) { - qdev->lrg_buf_index = 0; - } - curr_ial_ptr++; /* 64-bit pointers require two incs. */ - curr_ial_ptr++; - } + /* start of first buffer */ + lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr); + lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index]; + qdev->lrg_buf_release_cnt++; + if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS) + qdev->lrg_buf_index = 0; + curr_ial_ptr++; /* 64-bit pointers require two incs. */ + curr_ial_ptr++; /* start of second buffer */ lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr); @@ -1811,8 +1778,7 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev, qdev->ndev->last_rx = jiffies; lrg_buf_cb2->skb = NULL; - if (qdev->device_id == QL3022_DEVICE_ID) - ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb1); + ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb1); ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb2); } @@ -1824,7 +1790,7 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, struct ql_rcv_buf_cb *lrg_buf_cb1 = NULL; struct ql_rcv_buf_cb *lrg_buf_cb2 = NULL; u32 *curr_ial_ptr; - struct sk_buff *skb1 = NULL, *skb2; + struct sk_buff *skb1, *skb2; struct net_device *ndev = qdev->ndev; u16 length = le16_to_cpu(ib_ip_rsp_ptr->length); u16 size = 0; @@ -1840,20 +1806,16 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset; qdev->small_buf_release_cnt++; - if (qdev->device_id == QL3022_DEVICE_ID) { - /* start of first buffer on 3022 */ - lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr); - lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index]; - qdev->lrg_buf_release_cnt++; - if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS) - qdev->lrg_buf_index = 0; - skb1 = lrg_buf_cb1->skb; - curr_ial_ptr++; /* 64-bit pointers require two incs. */ - curr_ial_ptr++; - size = ETH_HLEN; - if (*((u16 *) skb1->data) != 0xFFFF) - size += VLAN_ETH_HLEN - ETH_HLEN; - } + /* start of first buffer */ + lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr); + lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index]; + + qdev->lrg_buf_release_cnt++; + if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS) + qdev->lrg_buf_index = 0; + skb1 = lrg_buf_cb1->skb; + curr_ial_ptr++; /* 64-bit pointers require two incs. */ + curr_ial_ptr++; /* start of second buffer */ lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr); @@ -1863,6 +1825,18 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS) qdev->lrg_buf_index = 0; + qdev->stats.rx_packets++; + qdev->stats.rx_bytes += length; + + /* + * Copy the ethhdr from first buffer to second. This + * is necessary for IP completions. + */ + if (*((u16 *) skb1->data) != 0xFFFF) + size = VLAN_ETH_HLEN; + else + size = ETH_HLEN; + skb_put(skb2, length); /* Just the second buffer length here. */ pci_unmap_single(qdev->pdev, pci_unmap_addr(lrg_buf_cb2, mapaddr), @@ -1870,40 +1844,16 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, PCI_DMA_FROMDEVICE); prefetch(skb2->data); - skb2->ip_summed = CHECKSUM_NONE; - if (qdev->device_id == QL3022_DEVICE_ID) { - /* - * Copy the ethhdr from first buffer to second. This - * is necessary for 3022 IP completions. - */ - memcpy(skb_push(skb2, size), skb1->data + VLAN_ID_LEN, size); - } else { - u16 checksum = le16_to_cpu(ib_ip_rsp_ptr->checksum); - if (checksum & - (IB_IP_IOCB_RSP_3032_ICE | - IB_IP_IOCB_RSP_3032_CE | - IB_IP_IOCB_RSP_3032_NUC)) { - printk(KERN_ERR - "%s: Bad checksum for this %s packet, checksum = %x.\n", - __func__, - ((checksum & - IB_IP_IOCB_RSP_3032_TCP) ? "TCP" : - "UDP"),checksum); - } else if (checksum & IB_IP_IOCB_RSP_3032_TCP) { - skb2->ip_summed = CHECKSUM_UNNECESSARY; - } - } + memcpy(skb_push(skb2, size), skb1->data + VLAN_ID_LEN, size); skb2->dev = qdev->ndev; + skb2->ip_summed = CHECKSUM_NONE; skb2->protocol = eth_type_trans(skb2, qdev->ndev); netif_receive_skb(skb2); - qdev->stats.rx_packets++; - qdev->stats.rx_bytes += length; ndev->last_rx = jiffies; lrg_buf_cb2->skb = NULL; - if (qdev->device_id == QL3022_DEVICE_ID) - ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb1); + ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb1); ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb2); } @@ -1930,14 +1880,12 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev, break; case OPCODE_IB_MAC_IOCB: - case OPCODE_IB_3032_MAC_IOCB: ql_process_mac_rx_intr(qdev, (struct ib_mac_iocb_rsp *) net_rsp); (*rx_cleaned)++; break; case OPCODE_IB_IP_IOCB: - case OPCODE_IB_3032_IP_IOCB: ql_process_macip_rx_intr(qdev, (struct ib_ip_iocb_rsp *) net_rsp); (*rx_cleaned)++; @@ -2084,96 +2032,13 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id) return IRQ_RETVAL(handled); } -/* - * Get the total number of segments needed for the - * given number of fragments. This is necessary because - * outbound address lists (OAL) will be used when more than - * two frags are given. Each address list has 5 addr/len - * pairs. The 5th pair in each AOL is used to point to - * the next AOL if more frags are coming. - * That is why the frags:segment count ratio is not linear. - */ -static int ql_get_seg_count(unsigned short frags) -{ - switch(frags) { - case 0: return 1; /* just the skb->data seg */ - case 1: return 2; /* skb->data + 1 frag */ - case 2: return 3; /* skb->data + 2 frags */ - case 3: return 5; /* skb->data + 1 frag + 1 AOL containting 2 frags */ - case 4: return 6; - case 5: return 7; - case 6: return 8; - case 7: return 10; - case 8: return 11; - case 9: return 12; - case 10: return 13; - case 11: return 15; - case 12: return 16; - case 13: return 17; - case 14: return 18; - case 15: return 20; - case 16: return 21; - case 17: return 22; - case 18: return 23; - } - return -1; -} - -static void ql_hw_csum_setup(struct sk_buff *skb, - struct ob_mac_iocb_req *mac_iocb_ptr) -{ - struct ethhdr *eth; - struct iphdr *ip = NULL; - u8 offset = ETH_HLEN; - - eth = (struct ethhdr *)(skb->data); - - if (eth->h_proto == __constant_htons(ETH_P_IP)) { - ip = (struct iphdr *)&skb->data[ETH_HLEN]; - } else if (eth->h_proto == htons(ETH_P_8021Q) && - ((struct vlan_ethhdr *)skb->data)-> - h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) { - ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN]; - offset = VLAN_ETH_HLEN; - } - - if (ip) { - if (ip->protocol == IPPROTO_TCP) { - mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC; - mac_iocb_ptr->ip_hdr_off = offset; - mac_iocb_ptr->ip_hdr_len = ip->ihl; - } else if (ip->protocol == IPPROTO_UDP) { - mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC; - mac_iocb_ptr->ip_hdr_off = offset; - mac_iocb_ptr->ip_hdr_len = ip->ihl; - } - } -} - -/* - * The difference between 3022 and 3032 sends: - * 3022 only supports a simple single segment transmission. - * 3032 supports checksumming and scatter/gather lists (fragments). - * The 3032 supports sglists by using the 3 addr/len pairs (ALP) - * in the IOCB plus a chain of outbound address lists (OAL) that - * each contain 5 ALPs. The last ALP of the IOCB (3rd) or OAL (5th) - * will used to point to an OAL when more ALP entries are required. - * The IOCB is always the top of the chain followed by one or more - * OALs (when necessary). - */ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev) { struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev); struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers; struct ql_tx_buf_cb *tx_cb; - u32 tot_len = skb->len; - struct oal *oal; - struct oal_entry *oal_entry; - int len; struct ob_mac_iocb_req *mac_iocb_ptr; u64 map; - int seg_cnt, seg = 0; - int frag_cnt = (int)skb_shinfo(skb)->nr_frags; if (unlikely(atomic_read(&qdev->tx_count) < 2)) { if (!netif_queue_stopped(ndev)) @@ -2181,79 +2046,21 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_BUSY; } tx_cb = &qdev->tx_buf[qdev->req_producer_index] ; - seg_cnt = tx_cb->seg_count = ql_get_seg_count((skb_shinfo(skb)->nr_frags)); - if(seg_cnt == -1) { - printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__); - return NETDEV_TX_OK; - - } mac_iocb_ptr = tx_cb->queue_entry; memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req)); mac_iocb_ptr->opcode = qdev->mac_ob_opcode; mac_iocb_ptr->flags |= qdev->mb_bit_mask; mac_iocb_ptr->transaction_id = qdev->req_producer_index; - mac_iocb_ptr->data_len = cpu_to_le16((u16) tot_len); + mac_iocb_ptr->data_len = cpu_to_le16((u16) skb->len); tx_cb->skb = skb; - if (skb->ip_summed == CHECKSUM_PARTIAL) - ql_hw_csum_setup(skb, mac_iocb_ptr); - len = skb_headlen(skb); - map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE); - oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low; - oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); - oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); - oal_entry->len = cpu_to_le32(len); - pci_unmap_addr_set(&tx_cb->map[seg], mapaddr, map); - pci_unmap_len_set(&tx_cb->map[seg], maplen, len); - seg++; - - if (!skb_shinfo(skb)->nr_frags) { - /* Terminate the last segment. */ - oal_entry->len = - cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY); - } else { - int i; - oal = tx_cb->oal; - for (i=0; ifrags[i]; - oal_entry++; - if ((seg == 2 && seg_cnt > 3) || /* Check for continuation */ - (seg == 7 && seg_cnt > 8) || /* requirements. It's strange */ - (seg == 12 && seg_cnt > 13) || /* but necessary. */ - (seg == 17 && seg_cnt > 18)) { - /* Continuation entry points to outbound address list. */ - map = pci_map_single(qdev->pdev, oal, - sizeof(struct oal), - PCI_DMA_TODEVICE); - oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); - oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); - oal_entry->len = - cpu_to_le32(sizeof(struct oal) | - OAL_CONT_ENTRY); - pci_unmap_addr_set(&tx_cb->map[seg], mapaddr, - map); - pci_unmap_len_set(&tx_cb->map[seg], maplen, - len); - oal_entry = (struct oal_entry *)oal; - oal++; - seg++; - } + map = pci_map_single(qdev->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + mac_iocb_ptr->buf_addr0_low = cpu_to_le32(LS_64BITS(map)); + mac_iocb_ptr->buf_addr0_high = cpu_to_le32(MS_64BITS(map)); + mac_iocb_ptr->buf_0_len = cpu_to_le32(skb->len | OB_MAC_IOCB_REQ_E); + pci_unmap_addr_set(tx_cb, mapaddr, map); + pci_unmap_len_set(tx_cb, maplen, skb->len); + atomic_dec(&qdev->tx_count); - map = - pci_map_page(qdev->pdev, frag->page, - frag->page_offset, frag->size, - PCI_DMA_TODEVICE); - oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map)); - oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map)); - oal_entry->len = cpu_to_le32(frag->size); - pci_unmap_addr_set(&tx_cb->map[seg], mapaddr, map); - pci_unmap_len_set(&tx_cb->map[seg], maplen, - frag->size); - } - /* Terminate the last segment. */ - oal_entry->len = - cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY); - } - wmb(); qdev->req_producer_index++; if (qdev->req_producer_index == NUM_REQ_Q_ENTRIES) qdev->req_producer_index = 0; @@ -2267,10 +2074,8 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev) printk(KERN_DEBUG PFX "%s: tx queued, slot %d, len %d\n", ndev->name, qdev->req_producer_index, skb->len); - atomic_dec(&qdev->tx_count); return NETDEV_TX_OK; } - static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) { qdev->req_q_size = @@ -2554,22 +2359,7 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev) return 0; } -static void ql_free_send_free_list(struct ql3_adapter *qdev) -{ - struct ql_tx_buf_cb *tx_cb; - int i; - - tx_cb = &qdev->tx_buf[0]; - for (i = 0; i < NUM_REQ_Q_ENTRIES; i++) { - if (tx_cb->oal) { - kfree(tx_cb->oal); - tx_cb->oal = NULL; - } - tx_cb++; - } -} - -static int ql_create_send_free_list(struct ql3_adapter *qdev) +static void ql_create_send_free_list(struct ql3_adapter *qdev) { struct ql_tx_buf_cb *tx_cb; int i; @@ -2578,16 +2368,11 @@ static int ql_create_send_free_list(struct ql3_adapter *qdev) /* Create free list of transmit buffers */ for (i = 0; i < NUM_REQ_Q_ENTRIES; i++) { - tx_cb = &qdev->tx_buf[i]; tx_cb->skb = NULL; tx_cb->queue_entry = req_q_curr; req_q_curr++; - tx_cb->oal = kmalloc(512, GFP_KERNEL); - if (tx_cb->oal == NULL) - return -1; } - return 0; } static int ql_alloc_mem_resources(struct ql3_adapter *qdev) @@ -2662,14 +2447,12 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev) /* Initialize the large buffer queue. */ ql_init_large_buffers(qdev); - if (ql_create_send_free_list(qdev)) - goto err_free_list; + ql_create_send_free_list(qdev); qdev->rsp_current = qdev->rsp_q_virt_addr; return 0; -err_free_list: - ql_free_send_free_list(qdev); + err_small_buffers: ql_free_buffer_queues(qdev); err_buffer_queues: @@ -2685,7 +2468,6 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev) static void ql_free_mem_resources(struct ql3_adapter *qdev) { - ql_free_send_free_list(qdev); ql_free_large_buffers(qdev); ql_free_small_buffers(qdev); ql_free_buffer_queues(qdev); @@ -2984,20 +2766,11 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev) } /* Enable Ethernet Function */ - if (qdev->device_id == QL3032_DEVICE_ID) { - value = - (QL3032_PORT_CONTROL_EF | QL3032_PORT_CONTROL_KIE | - QL3032_PORT_CONTROL_EIv6 | QL3032_PORT_CONTROL_EIv4); - ql_write_page0_reg(qdev, &port_regs->functionControl, - ((value << 16) | value)); - } else { - value = - (PORT_CONTROL_EF | PORT_CONTROL_ET | PORT_CONTROL_EI | - PORT_CONTROL_HH); - ql_write_page0_reg(qdev, &port_regs->portControl, - ((value << 16) | value)); - } - + value = + (PORT_CONTROL_EF | PORT_CONTROL_ET | PORT_CONTROL_EI | + PORT_CONTROL_HH); + ql_write_page0_reg(qdev, &port_regs->portControl, + ((value << 16) | value)); out: return status; @@ -3144,10 +2917,8 @@ static void ql_display_dev_info(struct net_device *ndev) struct pci_dev *pdev = qdev->pdev; printk(KERN_INFO PFX - "\n%s Adapter %d RevisionID %d found %s on PCI slot %d.\n", - DRV_NAME, qdev->index, qdev->chip_rev_id, - (qdev->device_id == QL3032_DEVICE_ID) ? "QLA3032" : "QLA3022", - qdev->pci_slot); + "\n%s Adapter %d RevisionID %d found on PCI slot %d.\n", + DRV_NAME, qdev->index, qdev->chip_rev_id, qdev->pci_slot); printk(KERN_INFO PFX "%s Interface.\n", test_bit(QL_LINK_OPTICAL,&qdev->flags) ? "OPTICAL" : "COPPER"); @@ -3441,22 +3212,15 @@ static void ql_reset_work(struct work_struct *work) * Loop through the active list and return the skb. */ for (i = 0; i < NUM_REQ_Q_ENTRIES; i++) { - int j; tx_cb = &qdev->tx_buf[i]; if (tx_cb->skb) { + printk(KERN_DEBUG PFX "%s: Freeing lost SKB.\n", qdev->ndev->name); pci_unmap_single(qdev->pdev, - pci_unmap_addr(&tx_cb->map[0], mapaddr), - pci_unmap_len(&tx_cb->map[0], maplen), - PCI_DMA_TODEVICE); - for(j=1;jseg_count;j++) { - pci_unmap_page(qdev->pdev, - pci_unmap_addr(&tx_cb->map[j],mapaddr), - pci_unmap_len(&tx_cb->map[j],maplen), - PCI_DMA_TODEVICE); - } + pci_unmap_addr(tx_cb, mapaddr), + pci_unmap_len(tx_cb, maplen), PCI_DMA_TODEVICE); dev_kfree_skb(tx_cb->skb); tx_cb->skb = NULL; } @@ -3615,24 +3379,21 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, &pdev->dev); + if (pci_using_dac) + ndev->features |= NETIF_F_HIGHDMA; + pci_set_drvdata(pdev, ndev); qdev = netdev_priv(ndev); qdev->index = cards_found; qdev->ndev = ndev; qdev->pdev = pdev; - qdev->device_id = pci_entry->device; qdev->port_link_state = LS_DOWN; if (msi) qdev->msi = 1; qdev->msg_enable = netif_msg_init(debug, default_msg); - if (pci_using_dac) - ndev->features |= NETIF_F_HIGHDMA; - if (qdev->device_id == QL3032_DEVICE_ID) - ndev->features |= (NETIF_F_HW_CSUM | NETIF_F_SG); - qdev->mem_map_registers = ioremap_nocache(pci_resource_start(pdev, 1), pci_resource_len(qdev->pdev, 1)); diff --git a/trunk/drivers/net/qla3xxx.h b/trunk/drivers/net/qla3xxx.h old mode 100755 new mode 100644 index b2d76ea68827..ea94de7fd071 --- a/trunk/drivers/net/qla3xxx.h +++ b/trunk/drivers/net/qla3xxx.h @@ -21,9 +21,7 @@ #define OPCODE_UPDATE_NCB_IOCB 0xF0 #define OPCODE_IB_MAC_IOCB 0xF9 -#define OPCODE_IB_3032_MAC_IOCB 0x09 #define OPCODE_IB_IP_IOCB 0xFA -#define OPCODE_IB_3032_IP_IOCB 0x0A #define OPCODE_IB_TCP_IOCB 0xFB #define OPCODE_DUMP_PROTO_IOCB 0xFE #define OPCODE_BUFFER_ALERT_IOCB 0xFB @@ -39,23 +37,18 @@ struct ob_mac_iocb_req { u8 opcode; u8 flags; -#define OB_MAC_IOCB_REQ_MA 0xe0 -#define OB_MAC_IOCB_REQ_F 0x10 -#define OB_MAC_IOCB_REQ_X 0x08 +#define OB_MAC_IOCB_REQ_MA 0xC0 +#define OB_MAC_IOCB_REQ_F 0x20 +#define OB_MAC_IOCB_REQ_X 0x10 #define OB_MAC_IOCB_REQ_D 0x02 #define OB_MAC_IOCB_REQ_I 0x01 - u8 flags1; -#define OB_3032MAC_IOCB_REQ_IC 0x04 -#define OB_3032MAC_IOCB_REQ_TC 0x02 -#define OB_3032MAC_IOCB_REQ_UC 0x01 - u8 reserved0; + __le16 reserved0; __le32 transaction_id; __le16 data_len; - u8 ip_hdr_off; - u8 ip_hdr_len; - __le32 reserved1; + __le16 reserved1; __le32 reserved2; + __le32 reserved3; __le32 buf_addr0_low; __le32 buf_addr0_high; __le32 buf_0_len; @@ -65,8 +58,8 @@ struct ob_mac_iocb_req { __le32 buf_addr2_low; __le32 buf_addr2_high; __le32 buf_2_len; - __le32 reserved3; __le32 reserved4; + __le32 reserved5; }; /* * The following constants define control bits for buffer @@ -81,7 +74,6 @@ struct ob_mac_iocb_rsp { u8 opcode; u8 flags; #define OB_MAC_IOCB_RSP_P 0x08 -#define OB_MAC_IOCB_RSP_L 0x04 #define OB_MAC_IOCB_RSP_S 0x02 #define OB_MAC_IOCB_RSP_I 0x01 @@ -93,7 +85,6 @@ struct ob_mac_iocb_rsp { struct ib_mac_iocb_rsp { u8 opcode; -#define IB_MAC_IOCB_RSP_V 0x80 u8 flags; #define IB_MAC_IOCB_RSP_S 0x80 #define IB_MAC_IOCB_RSP_H1 0x40 @@ -147,7 +138,6 @@ struct ob_ip_iocb_req { struct ob_ip_iocb_rsp { u8 opcode; u8 flags; -#define OB_MAC_IOCB_RSP_H 0x10 #define OB_MAC_IOCB_RSP_E 0x08 #define OB_MAC_IOCB_RSP_L 0x04 #define OB_MAC_IOCB_RSP_S 0x02 @@ -230,10 +220,6 @@ struct ob_tcp_iocb_rsp { struct ib_ip_iocb_rsp { u8 opcode; -#define IB_IP_IOCB_RSP_3032_V 0x80 -#define IB_IP_IOCB_RSP_3032_O 0x40 -#define IB_IP_IOCB_RSP_3032_I 0x20 -#define IB_IP_IOCB_RSP_3032_R 0x10 u8 flags; #define IB_IP_IOCB_RSP_S 0x80 #define IB_IP_IOCB_RSP_H1 0x40 @@ -244,12 +230,6 @@ struct ib_ip_iocb_rsp { __le16 length; __le16 checksum; -#define IB_IP_IOCB_RSP_3032_ICE 0x01 -#define IB_IP_IOCB_RSP_3032_CE 0x02 -#define IB_IP_IOCB_RSP_3032_NUC 0x04 -#define IB_IP_IOCB_RSP_3032_UDP 0x08 -#define IB_IP_IOCB_RSP_3032_TCP 0x10 -#define IB_IP_IOCB_RSP_3032_IPE 0x20 __le16 reserved; #define IB_IP_IOCB_RSP_R 0x01 __le32 ial_low; @@ -544,21 +524,6 @@ enum { IP_ADDR_INDEX_REG_FUNC_2_SEC = 0x0005, IP_ADDR_INDEX_REG_FUNC_3_PRI = 0x0006, IP_ADDR_INDEX_REG_FUNC_3_SEC = 0x0007, - IP_ADDR_INDEX_REG_6 = 0x0008, - IP_ADDR_INDEX_REG_OFFSET_MASK = 0x0030, - IP_ADDR_INDEX_REG_E = 0x0040, -}; -enum { - QL3032_PORT_CONTROL_DS = 0x0001, - QL3032_PORT_CONTROL_HH = 0x0002, - QL3032_PORT_CONTROL_EIv6 = 0x0004, - QL3032_PORT_CONTROL_EIv4 = 0x0008, - QL3032_PORT_CONTROL_ET = 0x0010, - QL3032_PORT_CONTROL_EF = 0x0020, - QL3032_PORT_CONTROL_DRM = 0x0040, - QL3032_PORT_CONTROL_RLB = 0x0080, - QL3032_PORT_CONTROL_RCB = 0x0100, - QL3032_PORT_CONTROL_KIE = 0x0200, }; enum { @@ -692,8 +657,7 @@ struct ql3xxx_port_registers { u32 internalRamWDataReg; u32 reclaimedBufferAddrRegLow; u32 reclaimedBufferAddrRegHigh; - u32 tcpConfiguration; - u32 functionControl; + u32 reserved[2]; u32 fpgaRevID; u32 localRamAddr; u32 localRamDataAutoIncr; @@ -999,7 +963,6 @@ struct eeprom_data { #define QL3XXX_VENDOR_ID 0x1077 #define QL3022_DEVICE_ID 0x3022 -#define QL3032_DEVICE_ID 0x3032 /* MTU & Frame Size stuff */ #define NORMAL_MTU_SIZE ETH_DATA_LEN @@ -1075,41 +1038,11 @@ struct ql_rcv_buf_cb { int index; }; -/* - * Original IOCB has 3 sg entries: - * first points to skb-data area - * second points to first frag - * third points to next oal. - * OAL has 5 entries: - * 1 thru 4 point to frags - * fifth points to next oal. - */ -#define MAX_OAL_CNT ((MAX_SKB_FRAGS-1)/4 + 1) - -struct oal_entry { - u32 dma_lo; - u32 dma_hi; - u32 len; -#define OAL_LAST_ENTRY 0x80000000 /* Last valid buffer in list. */ -#define OAL_CONT_ENTRY 0x40000000 /* points to an OAL. (continuation) */ - u32 reserved; -}; - -struct oal { - struct oal_entry oal_entry[5]; -}; - -struct map_list { - DECLARE_PCI_UNMAP_ADDR(mapaddr); - DECLARE_PCI_UNMAP_LEN(maplen); -}; - struct ql_tx_buf_cb { struct sk_buff *skb; struct ob_mac_iocb_req *queue_entry ; - int seg_count; - struct oal *oal; - struct map_list map[MAX_SKB_FRAGS+1]; + DECLARE_PCI_UNMAP_ADDR(mapaddr); + DECLARE_PCI_UNMAP_LEN(maplen); }; /* definitions for type field */ @@ -1256,7 +1189,6 @@ struct ql3_adapter { struct delayed_work reset_work; struct delayed_work tx_timeout_work; u32 max_frame_size; - u32 device_id; }; #endif /* _QLA3XXX_H_ */ diff --git a/trunk/drivers/net/s2io-regs.h b/trunk/drivers/net/s2io-regs.h index 0e345cbc2bf9..a914fef44309 100644 --- a/trunk/drivers/net/s2io-regs.h +++ b/trunk/drivers/net/s2io-regs.h @@ -15,7 +15,7 @@ #define TBD 0 -struct XENA_dev_config { +typedef struct _XENA_dev_config { /* Convention: mHAL_XXX is mask, vHAL_XXX is value */ /* General Control-Status Registers */ @@ -300,7 +300,6 @@ struct XENA_dev_config { u64 gpio_control; #define GPIO_CTRL_GPIO_0 BIT(8) u64 misc_control; -#define FAULT_BEHAVIOUR BIT(0) #define EXT_REQ_EN BIT(1) #define MISC_LINK_STABILITY_PRD(val) vBIT(val,29,3) @@ -852,9 +851,9 @@ struct XENA_dev_config { #define SPI_CONTROL_DONE BIT(6) u64 spi_data; #define SPI_DATA_WRITE(data,len) vBIT(data,0,len) -}; +} XENA_dev_config_t; -#define XENA_REG_SPACE sizeof(struct XENA_dev_config) +#define XENA_REG_SPACE sizeof(XENA_dev_config_t) #define XENA_EEPROM_SPACE (0x01 << 11) #endif /* _REGS_H */ diff --git a/trunk/drivers/net/s2io.c b/trunk/drivers/net/s2io.c index 639fbc0f16f3..1dd66b8ea0fa 100644 --- a/trunk/drivers/net/s2io.c +++ b/trunk/drivers/net/s2io.c @@ -77,7 +77,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.16.1" +#define DRV_VERSION "2.0.15.2" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -86,7 +86,7 @@ static char s2io_driver_version[] = DRV_VERSION; static int rxd_size[4] = {32,48,48,64}; static int rxd_count[4] = {127,85,85,63}; -static inline int RXD_IS_UP2DT(struct RxD_t *rxdp) +static inline int RXD_IS_UP2DT(RxD_t *rxdp) { int ret; @@ -111,9 +111,9 @@ static inline int RXD_IS_UP2DT(struct RxD_t *rxdp) #define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status)) #define PANIC 1 #define LOW 2 -static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring) +static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring) { - struct mac_info *mac_control; + mac_info_t *mac_control; mac_control = &sp->mac_control; if (rxb_size <= rxd_count[sp->rxd_mode]) @@ -286,7 +286,7 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = { static void s2io_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { - struct s2io_nic *nic = dev->priv; + nic_t *nic = dev->priv; unsigned long flags; spin_lock_irqsave(&nic->tx_lock, flags); @@ -297,7 +297,7 @@ static void s2io_vlan_rx_register(struct net_device *dev, /* Unregister the vlan */ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid) { - struct s2io_nic *nic = dev->priv; + nic_t *nic = dev->priv; unsigned long flags; spin_lock_irqsave(&nic->tx_lock, flags); @@ -401,10 +401,9 @@ S2IO_PARM_INT(lro, 0); * aggregation happens until we hit max IP pkt size(64K) */ S2IO_PARM_INT(lro_max_pkts, 0xFFFF); +#ifndef CONFIG_S2IO_NAPI S2IO_PARM_INT(indicate_max_pkts, 0); - -S2IO_PARM_INT(napi, 1); -S2IO_PARM_INT(ufo, 0); +#endif static unsigned int tx_fifo_len[MAX_TX_FIFOS] = {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; @@ -458,14 +457,14 @@ static int init_shared_mem(struct s2io_nic *nic) u32 size; void *tmp_v_addr, *tmp_v_addr_next; dma_addr_t tmp_p_addr, tmp_p_addr_next; - struct RxD_block *pre_rxd_blk = NULL; - int i, j, blk_cnt; + RxD_block_t *pre_rxd_blk = NULL; + int i, j, blk_cnt, rx_sz, tx_sz; int lst_size, lst_per_page; struct net_device *dev = nic->dev; unsigned long tmp; - struct buffAdd *ba; + buffAdd_t *ba; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; mac_control = &nic->mac_control; @@ -483,12 +482,13 @@ static int init_shared_mem(struct s2io_nic *nic) return -EINVAL; } - lst_size = (sizeof(struct TxD) * config->max_txds); + lst_size = (sizeof(TxD_t) * config->max_txds); + tx_sz = lst_size * size; lst_per_page = PAGE_SIZE / lst_size; for (i = 0; i < config->tx_fifo_num; i++) { int fifo_len = config->tx_cfg[i].fifo_len; - int list_holder_size = fifo_len * sizeof(struct list_info_hold); + int list_holder_size = fifo_len * sizeof(list_info_hold_t); mac_control->fifos[i].list_info = kmalloc(list_holder_size, GFP_KERNEL); if (!mac_control->fifos[i].list_info) { @@ -579,9 +579,10 @@ static int init_shared_mem(struct s2io_nic *nic) mac_control->rings[i].block_count; } if (nic->rxd_mode == RXD_MODE_1) - size = (size * (sizeof(struct RxD1))); + size = (size * (sizeof(RxD1_t))); else - size = (size * (sizeof(struct RxD3))); + size = (size * (sizeof(RxD3_t))); + rx_sz = size; for (i = 0; i < config->rx_ring_num; i++) { mac_control->rings[i].rx_curr_get_info.block_index = 0; @@ -599,7 +600,7 @@ static int init_shared_mem(struct s2io_nic *nic) (rxd_count[nic->rxd_mode] + 1); /* Allocating all the Rx blocks */ for (j = 0; j < blk_cnt; j++) { - struct rx_block_info *rx_blocks; + rx_block_info_t *rx_blocks; int l; rx_blocks = &mac_control->rings[i].rx_blocks[j]; @@ -619,11 +620,9 @@ static int init_shared_mem(struct s2io_nic *nic) memset(tmp_v_addr, 0, size); rx_blocks->block_virt_addr = tmp_v_addr; rx_blocks->block_dma_addr = tmp_p_addr; - rx_blocks->rxds = kmalloc(sizeof(struct rxd_info)* + rx_blocks->rxds = kmalloc(sizeof(rxd_info_t)* rxd_count[nic->rxd_mode], GFP_KERNEL); - if (!rx_blocks->rxds) - return -ENOMEM; for (l=0; lrxd_mode];l++) { rx_blocks->rxds[l].virt_addr = rx_blocks->block_virt_addr + @@ -646,7 +645,7 @@ static int init_shared_mem(struct s2io_nic *nic) mac_control->rings[i].rx_blocks[(j + 1) % blk_cnt].block_dma_addr; - pre_rxd_blk = (struct RxD_block *) tmp_v_addr; + pre_rxd_blk = (RxD_block_t *) tmp_v_addr; pre_rxd_blk->reserved_2_pNext_RxD_block = (unsigned long) tmp_v_addr_next; pre_rxd_blk->pNext_RxD_Blk_physical = @@ -662,14 +661,14 @@ static int init_shared_mem(struct s2io_nic *nic) blk_cnt = config->rx_cfg[i].num_rxd / (rxd_count[nic->rxd_mode]+ 1); mac_control->rings[i].ba = - kmalloc((sizeof(struct buffAdd *) * blk_cnt), + kmalloc((sizeof(buffAdd_t *) * blk_cnt), GFP_KERNEL); if (!mac_control->rings[i].ba) return -ENOMEM; for (j = 0; j < blk_cnt; j++) { int k = 0; mac_control->rings[i].ba[j] = - kmalloc((sizeof(struct buffAdd) * + kmalloc((sizeof(buffAdd_t) * (rxd_count[nic->rxd_mode] + 1)), GFP_KERNEL); if (!mac_control->rings[i].ba[j]) @@ -701,7 +700,7 @@ static int init_shared_mem(struct s2io_nic *nic) } /* Allocation and initialization of Statistics block */ - size = sizeof(struct stat_block); + size = sizeof(StatInfo_t); mac_control->stats_mem = pci_alloc_consistent (nic->pdev, size, &mac_control->stats_mem_phy); @@ -716,7 +715,7 @@ static int init_shared_mem(struct s2io_nic *nic) mac_control->stats_mem_sz = size; tmp_v_addr = mac_control->stats_mem; - mac_control->stats_info = (struct stat_block *) tmp_v_addr; + mac_control->stats_info = (StatInfo_t *) tmp_v_addr; memset(tmp_v_addr, 0, size); DBG_PRINT(INIT_DBG, "%s:Ring Mem PHY: 0x%llx\n", dev->name, (unsigned long long) tmp_p_addr); @@ -736,7 +735,7 @@ static void free_shared_mem(struct s2io_nic *nic) int i, j, blk_cnt, size; void *tmp_v_addr; dma_addr_t tmp_p_addr; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; int lst_size, lst_per_page; struct net_device *dev = nic->dev; @@ -747,7 +746,7 @@ static void free_shared_mem(struct s2io_nic *nic) mac_control = &nic->mac_control; config = &nic->config; - lst_size = (sizeof(struct TxD) * config->max_txds); + lst_size = (sizeof(TxD_t) * config->max_txds); lst_per_page = PAGE_SIZE / lst_size; for (i = 0; i < config->tx_fifo_num; i++) { @@ -810,7 +809,7 @@ static void free_shared_mem(struct s2io_nic *nic) if (!mac_control->rings[i].ba[j]) continue; while (k != rxd_count[nic->rxd_mode]) { - struct buffAdd *ba = + buffAdd_t *ba = &mac_control->rings[i].ba[j][k]; kfree(ba->ba_0_org); kfree(ba->ba_1_org); @@ -836,9 +835,9 @@ static void free_shared_mem(struct s2io_nic *nic) * s2io_verify_pci_mode - */ -static int s2io_verify_pci_mode(struct s2io_nic *nic) +static int s2io_verify_pci_mode(nic_t *nic) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0; int mode; @@ -869,9 +868,9 @@ static int bus_speed[8] = {33, 133, 133, 200, 266, 133, 200, 266}; /** * s2io_print_pci_mode - */ -static int s2io_print_pci_mode(struct s2io_nic *nic) +static int s2io_print_pci_mode(nic_t *nic) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0; int mode; struct config_param *config = &nic->config; @@ -939,13 +938,13 @@ static int s2io_print_pci_mode(struct s2io_nic *nic) static int init_nic(struct s2io_nic *nic) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; struct net_device *dev = nic->dev; register u64 val64 = 0; void __iomem *add; u32 time; int i, j; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; int dtx_cnt = 0; unsigned long long mem_share; @@ -1415,7 +1414,7 @@ static int init_nic(struct s2io_nic *nic) val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | TTI_DATA2_MEM_TX_UFC_B(0x20) | - TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80); + TTI_DATA2_MEM_TX_UFC_C(0x70) | TTI_DATA2_MEM_TX_UFC_D(0x80); writeq(val64, &bar0->tti_data2_mem); val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD; @@ -1611,8 +1610,7 @@ static int init_nic(struct s2io_nic *nic) * that does not start on an ADB to reduce disconnects. */ if (nic->device_type == XFRAME_II_DEVICE) { - val64 = FAULT_BEHAVIOUR | EXT_REQ_EN | - MISC_LINK_STABILITY_PRD(3); + val64 = EXT_REQ_EN | MISC_LINK_STABILITY_PRD(3); writeq(val64, &bar0->misc_control); val64 = readq(&bar0->pic_control2); val64 &= ~(BIT(13)|BIT(14)|BIT(15)); @@ -1628,7 +1626,7 @@ static int init_nic(struct s2io_nic *nic) #define LINK_UP_DOWN_INTERRUPT 1 #define MAC_RMAC_ERR_TIMER 2 -static int s2io_link_fault_indication(struct s2io_nic *nic) +static int s2io_link_fault_indication(nic_t *nic) { if (nic->intr_type != INTA) return MAC_RMAC_ERR_TIMER; @@ -1651,14 +1649,14 @@ static int s2io_link_fault_indication(struct s2io_nic *nic) static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0, temp64 = 0; /* Top level interrupt classification */ /* PIC Interrupts */ if ((mask & (TX_PIC_INTR | RX_PIC_INTR))) { /* Enable PIC Intrs in the general intr mask register */ - val64 = TXPIC_INT_M; + val64 = TXPIC_INT_M | PIC_RX_INT_M; if (flag == ENABLE_INTRS) { temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); @@ -1696,6 +1694,70 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) } } + /* DMA Interrupts */ + /* Enabling/Disabling Tx DMA interrupts */ + if (mask & TX_DMA_INTR) { + /* Enable TxDMA Intrs in the general intr mask register */ + val64 = TXDMA_INT_M; + if (flag == ENABLE_INTRS) { + temp64 = readq(&bar0->general_int_mask); + temp64 &= ~((u64) val64); + writeq(temp64, &bar0->general_int_mask); + /* + * Keep all interrupts other than PFC interrupt + * and PCC interrupt disabled in DMA level. + */ + val64 = DISABLE_ALL_INTRS & ~(TXDMA_PFC_INT_M | + TXDMA_PCC_INT_M); + writeq(val64, &bar0->txdma_int_mask); + /* + * Enable only the MISC error 1 interrupt in PFC block + */ + val64 = DISABLE_ALL_INTRS & (~PFC_MISC_ERR_1); + writeq(val64, &bar0->pfc_err_mask); + /* + * Enable only the FB_ECC error interrupt in PCC block + */ + val64 = DISABLE_ALL_INTRS & (~PCC_FB_ECC_ERR); + writeq(val64, &bar0->pcc_err_mask); + } else if (flag == DISABLE_INTRS) { + /* + * Disable TxDMA Intrs in the general intr mask + * register + */ + writeq(DISABLE_ALL_INTRS, &bar0->txdma_int_mask); + writeq(DISABLE_ALL_INTRS, &bar0->pfc_err_mask); + temp64 = readq(&bar0->general_int_mask); + val64 |= temp64; + writeq(val64, &bar0->general_int_mask); + } + } + + /* Enabling/Disabling Rx DMA interrupts */ + if (mask & RX_DMA_INTR) { + /* Enable RxDMA Intrs in the general intr mask register */ + val64 = RXDMA_INT_M; + if (flag == ENABLE_INTRS) { + temp64 = readq(&bar0->general_int_mask); + temp64 &= ~((u64) val64); + writeq(temp64, &bar0->general_int_mask); + /* + * All RxDMA block interrupts are disabled for now + * TODO + */ + writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask); + } else if (flag == DISABLE_INTRS) { + /* + * Disable RxDMA Intrs in the general intr mask + * register + */ + writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask); + temp64 = readq(&bar0->general_int_mask); + val64 |= temp64; + writeq(val64, &bar0->general_int_mask); + } + } + /* MAC Interrupts */ /* Enabling/Disabling MAC interrupts */ if (mask & (TX_MAC_INTR | RX_MAC_INTR)) { @@ -1722,6 +1784,53 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) } } + /* XGXS Interrupts */ + if (mask & (TX_XGXS_INTR | RX_XGXS_INTR)) { + val64 = TXXGXS_INT_M | RXXGXS_INT_M; + if (flag == ENABLE_INTRS) { + temp64 = readq(&bar0->general_int_mask); + temp64 &= ~((u64) val64); + writeq(temp64, &bar0->general_int_mask); + /* + * All XGXS block error interrupts are disabled for now + * TODO + */ + writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask); + } else if (flag == DISABLE_INTRS) { + /* + * Disable MC Intrs in the general intr mask register + */ + writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask); + temp64 = readq(&bar0->general_int_mask); + val64 |= temp64; + writeq(val64, &bar0->general_int_mask); + } + } + + /* Memory Controller(MC) interrupts */ + if (mask & MC_INTR) { + val64 = MC_INT_M; + if (flag == ENABLE_INTRS) { + temp64 = readq(&bar0->general_int_mask); + temp64 &= ~((u64) val64); + writeq(temp64, &bar0->general_int_mask); + /* + * Enable all MC Intrs. + */ + writeq(0x0, &bar0->mc_int_mask); + writeq(0x0, &bar0->mc_err_mask); + } else if (flag == DISABLE_INTRS) { + /* + * Disable MC Intrs in the general intr mask register + */ + writeq(DISABLE_ALL_INTRS, &bar0->mc_int_mask); + temp64 = readq(&bar0->general_int_mask); + val64 |= temp64; + writeq(val64, &bar0->general_int_mask); + } + } + + /* Tx traffic interrupts */ if (mask & TX_TRAFFIC_INTR) { val64 = TXTRAFFIC_INT_M; @@ -1768,36 +1877,41 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) } } -/** - * verify_pcc_quiescent- Checks for PCC quiescent state - * Return: 1 If PCC is quiescence - * 0 If PCC is not quiescence - */ -static int verify_pcc_quiescent(struct s2io_nic *sp, int flag) +static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc) { - int ret = 0, herc; - struct XENA_dev_config __iomem *bar0 = sp->bar0; - u64 val64 = readq(&bar0->adapter_status); - - herc = (sp->device_type == XFRAME_II_DEVICE); + int ret = 0; if (flag == FALSE) { - if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) { - if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE)) + if ((!herc && (rev_id >= 4)) || herc) { + if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) && + ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == + ADAPTER_STATUS_RC_PRC_QUIESCENT)) { ret = 1; - } else { - if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE)) + } + }else { + if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) && + ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == + ADAPTER_STATUS_RC_PRC_QUIESCENT)) { ret = 1; + } } } else { - if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) { + if ((!herc && (rev_id >= 4)) || herc) { if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) == - ADAPTER_STATUS_RMAC_PCC_IDLE)) + ADAPTER_STATUS_RMAC_PCC_IDLE) && + (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) || + ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == + ADAPTER_STATUS_RC_PRC_QUIESCENT))) { ret = 1; + } } else { if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) == - ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE)) + ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) && + (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) || + ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == + ADAPTER_STATUS_RC_PRC_QUIESCENT))) { ret = 1; + } } } @@ -1805,6 +1919,9 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag) } /** * verify_xena_quiescence - Checks whether the H/W is ready + * @val64 : Value read from adapter status register. + * @flag : indicates if the adapter enable bit was ever written once + * before. * Description: Returns whether the H/W is ready to go or not. Depending * on whether adapter enable bit was written or not the comparison * differs and the calling function passes the input argument flag to @@ -1813,63 +1930,24 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag) * 0 If Xena is not quiescence */ -static int verify_xena_quiescence(struct s2io_nic *sp) +static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag) { - int mode; - struct XENA_dev_config __iomem *bar0 = sp->bar0; - u64 val64 = readq(&bar0->adapter_status); - mode = s2io_verify_pci_mode(sp); + int ret = 0, herc; + u64 tmp64 = ~((u64) val64); + int rev_id = get_xena_rev_id(sp->pdev); - if (!(val64 & ADAPTER_STATUS_TDMA_READY)) { - DBG_PRINT(ERR_DBG, "%s", "TDMA is not ready!"); - return 0; - } - if (!(val64 & ADAPTER_STATUS_RDMA_READY)) { - DBG_PRINT(ERR_DBG, "%s", "RDMA is not ready!"); - return 0; - } - if (!(val64 & ADAPTER_STATUS_PFC_READY)) { - DBG_PRINT(ERR_DBG, "%s", "PFC is not ready!"); - return 0; - } - if (!(val64 & ADAPTER_STATUS_TMAC_BUF_EMPTY)) { - DBG_PRINT(ERR_DBG, "%s", "TMAC BUF is not empty!"); - return 0; - } - if (!(val64 & ADAPTER_STATUS_PIC_QUIESCENT)) { - DBG_PRINT(ERR_DBG, "%s", "PIC is not QUIESCENT!"); - return 0; - } - if (!(val64 & ADAPTER_STATUS_MC_DRAM_READY)) { - DBG_PRINT(ERR_DBG, "%s", "MC_DRAM is not ready!"); - return 0; - } - if (!(val64 & ADAPTER_STATUS_MC_QUEUES_READY)) { - DBG_PRINT(ERR_DBG, "%s", "MC_QUEUES is not ready!"); - return 0; - } - if (!(val64 & ADAPTER_STATUS_M_PLL_LOCK)) { - DBG_PRINT(ERR_DBG, "%s", "M_PLL is not locked!"); - return 0; + herc = (sp->device_type == XFRAME_II_DEVICE); + if (! + (tmp64 & + (ADAPTER_STATUS_TDMA_READY | ADAPTER_STATUS_RDMA_READY | + ADAPTER_STATUS_PFC_READY | ADAPTER_STATUS_TMAC_BUF_EMPTY | + ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY | + ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK | + ADAPTER_STATUS_P_PLL_LOCK))) { + ret = check_prc_pcc_state(val64, flag, rev_id, herc); } - /* - * In PCI 33 mode, the P_PLL is not used, and therefore, - * the the P_PLL_LOCK bit in the adapter_status register will - * not be asserted. - */ - if (!(val64 & ADAPTER_STATUS_P_PLL_LOCK) && - sp->device_type == XFRAME_II_DEVICE && mode != - PCI_MODE_PCI_33) { - DBG_PRINT(ERR_DBG, "%s", "P_PLL is not locked!"); - return 0; - } - if (!((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == - ADAPTER_STATUS_RC_PRC_QUIESCENT)) { - DBG_PRINT(ERR_DBG, "%s", "RC_PRC is not QUIESCENT!"); - return 0; - } - return 1; + return ret; } /** @@ -1880,9 +1958,9 @@ static int verify_xena_quiescence(struct s2io_nic *sp) * */ -static void fix_mac_address(struct s2io_nic * sp) +static void fix_mac_address(nic_t * sp) { - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; int i = 0; @@ -1908,11 +1986,11 @@ static void fix_mac_address(struct s2io_nic * sp) static int start_nic(struct s2io_nic *nic) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; struct net_device *dev = nic->dev; register u64 val64 = 0; u16 subid, i; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; mac_control = &nic->mac_control; @@ -1974,7 +2052,7 @@ static int start_nic(struct s2io_nic *nic) * it. */ val64 = readq(&bar0->adapter_status); - if (!verify_xena_quiescence(nic)) { + if (!verify_xena_quiescence(nic, val64, nic->device_enabled_once)) { DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name); DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n", (unsigned long long) val64); @@ -2017,12 +2095,11 @@ static int start_nic(struct s2io_nic *nic) /** * s2io_txdl_getskb - Get the skb from txdl, unmap and return skb */ -static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data, struct \ - TxD *txdlp, int get_off) +static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, int get_off) { - struct s2io_nic *nic = fifo_data->nic; + nic_t *nic = fifo_data->nic; struct sk_buff *skb; - struct TxD *txds; + TxD_t *txds; u16 j, frg_cnt; txds = txdlp; @@ -2036,7 +2113,7 @@ static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data, struct \ skb = (struct sk_buff *) ((unsigned long) txds->Host_Control); if (!skb) { - memset(txdlp, 0, (sizeof(struct TxD) * fifo_data->max_txds)); + memset(txdlp, 0, (sizeof(TxD_t) * fifo_data->max_txds)); return NULL; } pci_unmap_single(nic->pdev, (dma_addr_t) @@ -2055,7 +2132,7 @@ static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data, struct \ frag->size, PCI_DMA_TODEVICE); } } - memset(txdlp,0, (sizeof(struct TxD) * fifo_data->max_txds)); + memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds)); return(skb); } @@ -2071,9 +2148,9 @@ static void free_tx_buffers(struct s2io_nic *nic) { struct net_device *dev = nic->dev; struct sk_buff *skb; - struct TxD *txdp; + TxD_t *txdp; int i, j; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; int cnt = 0; @@ -2082,7 +2159,7 @@ static void free_tx_buffers(struct s2io_nic *nic) for (i = 0; i < config->tx_fifo_num; i++) { for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) { - txdp = (struct TxD *) mac_control->fifos[i].list_info[j]. + txdp = (TxD_t *) mac_control->fifos[i].list_info[j]. list_virt_addr; skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j); if (skb) { @@ -2110,10 +2187,10 @@ static void free_tx_buffers(struct s2io_nic *nic) static void stop_nic(struct s2io_nic *nic) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0; u16 interruptible; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; mac_control = &nic->mac_control; @@ -2131,15 +2208,14 @@ static void stop_nic(struct s2io_nic *nic) writeq(val64, &bar0->adapter_control); } -static int fill_rxd_3buf(struct s2io_nic *nic, struct RxD_t *rxdp, struct \ - sk_buff *skb) +static int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb) { struct net_device *dev = nic->dev; struct sk_buff *frag_list; void *tmp; /* Buffer-1 receives L3/L4 headers */ - ((struct RxD3*)rxdp)->Buffer1_ptr = pci_map_single + ((RxD3_t*)rxdp)->Buffer1_ptr = pci_map_single (nic->pdev, skb->data, l3l4hdr_size + 4, PCI_DMA_FROMDEVICE); @@ -2150,14 +2226,13 @@ static int fill_rxd_3buf(struct s2io_nic *nic, struct RxD_t *rxdp, struct \ return -ENOMEM ; } frag_list = skb_shinfo(skb)->frag_list; - skb->truesize += frag_list->truesize; frag_list->next = NULL; tmp = (void *)ALIGN((long)frag_list->data, ALIGN_SIZE + 1); frag_list->data = tmp; frag_list->tail = tmp; /* Buffer-2 receives L4 data payload */ - ((struct RxD3*)rxdp)->Buffer2_ptr = pci_map_single(nic->pdev, + ((RxD3_t*)rxdp)->Buffer2_ptr = pci_map_single(nic->pdev, frag_list->data, dev->mtu, PCI_DMA_FROMDEVICE); rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4); @@ -2191,16 +2266,18 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) { struct net_device *dev = nic->dev; struct sk_buff *skb; - struct RxD_t *rxdp; + RxD_t *rxdp; int off, off1, size, block_no, block_no1; u32 alloc_tab = 0; u32 alloc_cnt; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; u64 tmp; - struct buffAdd *ba; + buffAdd_t *ba; +#ifndef CONFIG_S2IO_NAPI unsigned long flags; - struct RxD_t *first_rxdp = NULL; +#endif + RxD_t *first_rxdp = NULL; mac_control = &nic->mac_control; config = &nic->config; @@ -2243,15 +2320,12 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n", dev->name, rxdp); } - if(!napi) { - spin_lock_irqsave(&nic->put_lock, flags); - mac_control->rings[ring_no].put_pos = - (block_no * (rxd_count[nic->rxd_mode] + 1)) + off; - spin_unlock_irqrestore(&nic->put_lock, flags); - } else { - mac_control->rings[ring_no].put_pos = - (block_no * (rxd_count[nic->rxd_mode] + 1)) + off; - } +#ifndef CONFIG_S2IO_NAPI + spin_lock_irqsave(&nic->put_lock, flags); + mac_control->rings[ring_no].put_pos = + (block_no * (rxd_count[nic->rxd_mode] + 1)) + off; + spin_unlock_irqrestore(&nic->put_lock, flags); +#endif if ((rxdp->Control_1 & RXD_OWN_XENA) && ((nic->rxd_mode >= RXD_MODE_3A) && (rxdp->Control_2 & BIT(0)))) { @@ -2282,9 +2356,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) } if (nic->rxd_mode == RXD_MODE_1) { /* 1 buffer mode - normal operation mode */ - memset(rxdp, 0, sizeof(struct RxD1)); + memset(rxdp, 0, sizeof(RxD1_t)); skb_reserve(skb, NET_IP_ALIGN); - ((struct RxD1*)rxdp)->Buffer0_ptr = pci_map_single + ((RxD1_t*)rxdp)->Buffer0_ptr = pci_map_single (nic->pdev, skb->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN); @@ -2301,7 +2375,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) * payload */ - memset(rxdp, 0, sizeof(struct RxD3)); + memset(rxdp, 0, sizeof(RxD3_t)); ba = &mac_control->rings[ring_no].ba[block_no][off]; skb_reserve(skb, BUF0_LEN); tmp = (u64)(unsigned long) skb->data; @@ -2310,13 +2384,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) skb->data = (void *) (unsigned long)tmp; skb->tail = (void *) (unsigned long)tmp; - if (!(((struct RxD3*)rxdp)->Buffer0_ptr)) - ((struct RxD3*)rxdp)->Buffer0_ptr = + if (!(((RxD3_t*)rxdp)->Buffer0_ptr)) + ((RxD3_t*)rxdp)->Buffer0_ptr = pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); else pci_dma_sync_single_for_device(nic->pdev, - (dma_addr_t) ((struct RxD3*)rxdp)->Buffer0_ptr, + (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); if (nic->rxd_mode == RXD_MODE_3B) { @@ -2326,13 +2400,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) * Buffer2 will have L3/L4 header plus * L4 payload */ - ((struct RxD3*)rxdp)->Buffer2_ptr = pci_map_single + ((RxD3_t*)rxdp)->Buffer2_ptr = pci_map_single (nic->pdev, skb->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); /* Buffer-1 will be dummy buffer. Not used */ - if (!(((struct RxD3*)rxdp)->Buffer1_ptr)) { - ((struct RxD3*)rxdp)->Buffer1_ptr = + if (!(((RxD3_t*)rxdp)->Buffer1_ptr)) { + ((RxD3_t*)rxdp)->Buffer1_ptr = pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN, PCI_DMA_FROMDEVICE); @@ -2392,9 +2466,9 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) struct net_device *dev = sp->dev; int j; struct sk_buff *skb; - struct RxD_t *rxdp; - struct mac_info *mac_control; - struct buffAdd *ba; + RxD_t *rxdp; + mac_info_t *mac_control; + buffAdd_t *ba; mac_control = &sp->mac_control; for (j = 0 ; j < rxd_count[sp->rxd_mode]; j++) { @@ -2407,41 +2481,41 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk) } if (sp->rxd_mode == RXD_MODE_1) { pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD1*)rxdp)->Buffer0_ptr, + ((RxD1_t*)rxdp)->Buffer0_ptr, dev->mtu + HEADER_ETHERNET_II_802_3_SIZE + HEADER_802_2_SIZE + HEADER_SNAP_SIZE, PCI_DMA_FROMDEVICE); - memset(rxdp, 0, sizeof(struct RxD1)); + memset(rxdp, 0, sizeof(RxD1_t)); } else if(sp->rxd_mode == RXD_MODE_3B) { ba = &mac_control->rings[ring_no]. ba[blk][j]; pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, + ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer1_ptr, + ((RxD3_t*)rxdp)->Buffer1_ptr, BUF1_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, + ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu + 4, PCI_DMA_FROMDEVICE); - memset(rxdp, 0, sizeof(struct RxD3)); + memset(rxdp, 0, sizeof(RxD3_t)); } else { pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, BUF0_LEN, + ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer1_ptr, + ((RxD3_t*)rxdp)->Buffer1_ptr, l3l4hdr_size + 4, PCI_DMA_FROMDEVICE); pci_unmap_single(sp->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, dev->mtu, + ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu, PCI_DMA_FROMDEVICE); - memset(rxdp, 0, sizeof(struct RxD3)); + memset(rxdp, 0, sizeof(RxD3_t)); } dev_kfree_skb(skb); atomic_dec(&sp->rx_bufs_left[ring_no]); @@ -2461,7 +2535,7 @@ static void free_rx_buffers(struct s2io_nic *sp) { struct net_device *dev = sp->dev; int i, blk = 0, buf_cnt = 0; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; mac_control = &sp->mac_control; @@ -2494,13 +2568,15 @@ static void free_rx_buffers(struct s2io_nic *sp) * 0 on success and 1 if there are No Rx packets to be processed. */ +#if defined(CONFIG_S2IO_NAPI) static int s2io_poll(struct net_device *dev, int *budget) { - struct s2io_nic *nic = dev->priv; + nic_t *nic = dev->priv; int pkt_cnt = 0, org_pkts_to_process; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; + u64 val64 = 0xFFFFFFFFFFFFFFFFULL; int i; atomic_inc(&nic->isr_cnt); @@ -2512,8 +2588,8 @@ static int s2io_poll(struct net_device *dev, int *budget) nic->pkts_to_process = dev->quota; org_pkts_to_process = nic->pkts_to_process; - writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); - readl(&bar0->rx_traffic_int); + writeq(val64, &bar0->rx_traffic_int); + val64 = readl(&bar0->rx_traffic_int); for (i = 0; i < config->rx_ring_num; i++) { rx_intr_handler(&mac_control->rings[i]); @@ -2539,7 +2615,7 @@ static int s2io_poll(struct net_device *dev, int *budget) } /* Re enable the Rx interrupts. */ writeq(0x0, &bar0->rx_traffic_mask); - readl(&bar0->rx_traffic_mask); + val64 = readl(&bar0->rx_traffic_mask); atomic_dec(&nic->isr_cnt); return 0; @@ -2557,6 +2633,7 @@ static int s2io_poll(struct net_device *dev, int *budget) atomic_dec(&nic->isr_cnt); return 1; } +#endif #ifdef CONFIG_NET_POLL_CONTROLLER /** @@ -2570,10 +2647,10 @@ static int s2io_poll(struct net_device *dev, int *budget) */ static void s2io_netpoll(struct net_device *dev) { - struct s2io_nic *nic = dev->priv; - struct mac_info *mac_control; + nic_t *nic = dev->priv; + mac_info_t *mac_control; struct config_param *config; - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; u64 val64 = 0xFFFFFFFFFFFFFFFFULL; int i; @@ -2622,15 +2699,17 @@ static void s2io_netpoll(struct net_device *dev) * Return Value: * NONE. */ -static void rx_intr_handler(struct ring_info *ring_data) +static void rx_intr_handler(ring_info_t *ring_data) { - struct s2io_nic *nic = ring_data->nic; + nic_t *nic = ring_data->nic; struct net_device *dev = (struct net_device *) nic->dev; int get_block, put_block, put_offset; - struct rx_curr_get_info get_info, put_info; - struct RxD_t *rxdp; + rx_curr_get_info_t get_info, put_info; + RxD_t *rxdp; struct sk_buff *skb; +#ifndef CONFIG_S2IO_NAPI int pkt_cnt = 0; +#endif int i; spin_lock(&nic->rx_lock); @@ -2643,21 +2722,19 @@ static void rx_intr_handler(struct ring_info *ring_data) get_info = ring_data->rx_curr_get_info; get_block = get_info.block_index; - memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info)); + put_info = ring_data->rx_curr_put_info; put_block = put_info.block_index; rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr; - if (!napi) { - spin_lock(&nic->put_lock); - put_offset = ring_data->put_pos; - spin_unlock(&nic->put_lock); - } else - put_offset = ring_data->put_pos; - +#ifndef CONFIG_S2IO_NAPI + spin_lock(&nic->put_lock); + put_offset = ring_data->put_pos; + spin_unlock(&nic->put_lock); +#else + put_offset = (put_block * (rxd_count[nic->rxd_mode] + 1)) + + put_info.offset; +#endif while (RXD_IS_UP2DT(rxdp)) { - /* - * If your are next to put index then it's - * FIFO full condition - */ + /* If your are next to put index then it's FIFO full condition */ if ((get_block == put_block) && (get_info.offset + 1) == put_info.offset) { DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name); @@ -2673,7 +2750,7 @@ static void rx_intr_handler(struct ring_info *ring_data) } if (nic->rxd_mode == RXD_MODE_1) { pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD1*)rxdp)->Buffer0_ptr, + ((RxD1_t*)rxdp)->Buffer0_ptr, dev->mtu + HEADER_ETHERNET_II_802_3_SIZE + HEADER_802_2_SIZE + @@ -2681,22 +2758,22 @@ static void rx_intr_handler(struct ring_info *ring_data) PCI_DMA_FROMDEVICE); } else if (nic->rxd_mode == RXD_MODE_3B) { pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, + ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, + ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu + 4, PCI_DMA_FROMDEVICE); } else { pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer0_ptr, BUF0_LEN, + ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer1_ptr, + ((RxD3_t*)rxdp)->Buffer1_ptr, l3l4hdr_size + 4, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) - ((struct RxD3*)rxdp)->Buffer2_ptr, + ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu, PCI_DMA_FROMDEVICE); } prefetch(skb->data); @@ -2715,17 +2792,20 @@ static void rx_intr_handler(struct ring_info *ring_data) rxdp = ring_data->rx_blocks[get_block].block_virt_addr; } +#ifdef CONFIG_S2IO_NAPI nic->pkts_to_process -= 1; - if ((napi) && (!nic->pkts_to_process)) + if (!nic->pkts_to_process) break; +#else pkt_cnt++; if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts)) break; +#endif } if (nic->lro) { /* Clear all LRO sessions before exiting */ for (i=0; ilro0_n[i]; + lro_t *lro = &nic->lro0_n[i]; if (lro->in_use) { update_L3L4_header(nic, lro); queue_rx_frame(lro->parent); @@ -2749,17 +2829,17 @@ static void rx_intr_handler(struct ring_info *ring_data) * NONE */ -static void tx_intr_handler(struct fifo_info *fifo_data) +static void tx_intr_handler(fifo_info_t *fifo_data) { - struct s2io_nic *nic = fifo_data->nic; + nic_t *nic = fifo_data->nic; struct net_device *dev = (struct net_device *) nic->dev; - struct tx_curr_get_info get_info, put_info; + tx_curr_get_info_t get_info, put_info; struct sk_buff *skb; - struct TxD *txdlp; + TxD_t *txdlp; get_info = fifo_data->tx_curr_get_info; - memcpy(&put_info, &fifo_data->tx_curr_put_info, sizeof(put_info)); - txdlp = (struct TxD *) fifo_data->list_info[get_info.offset]. + put_info = fifo_data->tx_curr_put_info; + txdlp = (TxD_t *) fifo_data->list_info[get_info.offset]. list_virt_addr; while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) && (get_info.offset != put_info.offset) && @@ -2774,10 +2854,11 @@ static void tx_intr_handler(struct fifo_info *fifo_data) } if ((err >> 48) == 0xA) { DBG_PRINT(TX_DBG, "TxD returned due \ - to loss of link\n"); +to loss of link\n"); } else { - DBG_PRINT(ERR_DBG, "***TxD error %llx\n", err); + DBG_PRINT(ERR_DBG, "***TxD error \ +%llx\n", err); } } @@ -2796,7 +2877,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data) get_info.offset++; if (get_info.offset == get_info.fifo_len + 1) get_info.offset = 0; - txdlp = (struct TxD *) fifo_data->list_info + txdlp = (TxD_t *) fifo_data->list_info [get_info.offset].list_virt_addr; fifo_data->tx_curr_get_info.offset = get_info.offset; @@ -2821,8 +2902,8 @@ static void tx_intr_handler(struct fifo_info *fifo_data) static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev) { u64 val64 = 0x0; - struct s2io_nic *sp = dev->priv; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + nic_t *sp = dev->priv; + XENA_dev_config_t __iomem *bar0 = sp->bar0; //address transaction val64 = val64 | MDIO_MMD_INDX_ADDR(addr) @@ -2870,8 +2951,8 @@ static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev) { u64 val64 = 0x0; u64 rval64 = 0x0; - struct s2io_nic *sp = dev->priv; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + nic_t *sp = dev->priv; + XENA_dev_config_t __iomem *bar0 = sp->bar0; /* address transaction */ val64 = val64 | MDIO_MMD_INDX_ADDR(addr) @@ -2974,8 +3055,8 @@ static void s2io_updt_xpak_counter(struct net_device *dev) u64 val64 = 0x0; u64 addr = 0x0; - struct s2io_nic *sp = dev->priv; - struct stat_block *stat_info = sp->mac_control.stats_info; + nic_t *sp = dev->priv; + StatInfo_t *stat_info = sp->mac_control.stats_info; /* Check the communication with the MDIO slave */ addr = 0x0000; @@ -3073,12 +3154,10 @@ static void s2io_updt_xpak_counter(struct net_device *dev) static void alarm_intr_handler(struct s2io_nic *nic) { struct net_device *dev = (struct net_device *) nic->dev; - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0, err_reg = 0; u64 cnt; int i; - if (atomic_read(&nic->card_state) == CARD_DOWN) - return; nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0; /* Handling the XPAK counters update */ if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) { @@ -3218,25 +3297,6 @@ static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit) } return ret; } -/* - * check_pci_device_id - Checks if the device id is supported - * @id : device id - * Description: Function to check if the pci device id is supported by driver. - * Return value: Actual device id if supported else PCI_ANY_ID - */ -static u16 check_pci_device_id(u16 id) -{ - switch (id) { - case PCI_DEVICE_ID_HERC_WIN: - case PCI_DEVICE_ID_HERC_UNI: - return XFRAME_II_DEVICE; - case PCI_DEVICE_ID_S2IO_UNI: - case PCI_DEVICE_ID_S2IO_WIN: - return XFRAME_I_DEVICE; - default: - return PCI_ANY_ID; - } -} /** * s2io_reset - Resets the card. @@ -3248,58 +3308,43 @@ static u16 check_pci_device_id(u16 id) * void. */ -static void s2io_reset(struct s2io_nic * sp) +static void s2io_reset(nic_t * sp) { - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; u16 subid, pci_cmd; - int i; - u16 val16; - DBG_PRINT(INIT_DBG,"%s - Resetting XFrame card %s\n", - __FUNCTION__, sp->dev->name); /* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */ pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd)); - if (sp->device_type == XFRAME_II_DEVICE) { - int ret; - ret = pci_set_power_state(sp->pdev, 3); - if (!ret) - ret = pci_set_power_state(sp->pdev, 0); - else { - DBG_PRINT(ERR_DBG,"%s PME based SW_Reset failed!\n", - __FUNCTION__); - goto old_way; - } - msleep(20); - goto new_way; - } -old_way: val64 = SW_RESET_ALL; writeq(val64, &bar0->sw_reset); -new_way: + + /* + * At this stage, if the PCI write is indeed completed, the + * card is reset and so is the PCI Config space of the device. + * So a read cannot be issued at this stage on any of the + * registers to ensure the write into "sw_reset" register + * has gone through. + * Question: Is there any system call that will explicitly force + * all the write commands still pending on the bus to be pushed + * through? + * As of now I'am just giving a 250ms delay and hoping that the + * PCI write to sw_reset register is done by this time. + */ + msleep(250); if (strstr(sp->product_name, "CX4")) { msleep(750); } - msleep(250); - for (i = 0; i < S2IO_MAX_PCI_CONFIG_SPACE_REINIT; i++) { - - /* Restore the PCI state saved during initialization. */ - pci_restore_state(sp->pdev); - pci_read_config_word(sp->pdev, 0x2, &val16); - if (check_pci_device_id(val16) != (u16)PCI_ANY_ID) - break; - msleep(200); - } - - if (check_pci_device_id(val16) == (u16)PCI_ANY_ID) { - DBG_PRINT(ERR_DBG,"%s SW_Reset failed!\n", __FUNCTION__); - } - - pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, pci_cmd); + /* Restore the PCI state saved during initialization. */ + pci_restore_state(sp->pdev); + pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, + pci_cmd); s2io_init_pci(sp); + msleep(250); + /* Set swapper to enable I/O register access */ s2io_set_swapper(sp); @@ -3354,10 +3399,10 @@ static void s2io_reset(struct s2io_nic * sp) * SUCCESS on success and FAILURE on failure. */ -static int s2io_set_swapper(struct s2io_nic * sp) +static int s2io_set_swapper(nic_t * sp) { struct net_device *dev = sp->dev; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64, valt, valr; /* @@ -3482,9 +3527,9 @@ static int s2io_set_swapper(struct s2io_nic * sp) return SUCCESS; } -static int wait_for_msix_trans(struct s2io_nic *nic, int i) +static int wait_for_msix_trans(nic_t *nic, int i) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; u64 val64; int ret = 0, cnt = 0; @@ -3503,9 +3548,9 @@ static int wait_for_msix_trans(struct s2io_nic *nic, int i) return ret; } -static void restore_xmsi_data(struct s2io_nic *nic) +static void restore_xmsi_data(nic_t *nic) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; u64 val64; int i; @@ -3521,9 +3566,9 @@ static void restore_xmsi_data(struct s2io_nic *nic) } } -static void store_xmsi_data(struct s2io_nic *nic) +static void store_xmsi_data(nic_t *nic) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; u64 val64, addr, data; int i; @@ -3544,9 +3589,9 @@ static void store_xmsi_data(struct s2io_nic *nic) } } -int s2io_enable_msi(struct s2io_nic *nic) +int s2io_enable_msi(nic_t *nic) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; u16 msi_ctrl, msg_val; struct config_param *config = &nic->config; struct net_device *dev = nic->dev; @@ -3594,9 +3639,9 @@ int s2io_enable_msi(struct s2io_nic *nic) return 0; } -static int s2io_enable_msi_x(struct s2io_nic *nic) +static int s2io_enable_msi_x(nic_t *nic) { - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; u64 tx_mat, rx_mat; u16 msi_control; /* Temp variable */ int ret, i, j, msix_indx = 1; @@ -3704,7 +3749,7 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) static int s2io_open(struct net_device *dev) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; int err = 0; /* @@ -3757,7 +3802,7 @@ static int s2io_open(struct net_device *dev) static int s2io_close(struct net_device *dev) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; flush_scheduled_work(); netif_stop_queue(dev); @@ -3783,15 +3828,15 @@ static int s2io_close(struct net_device *dev) static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off; register u64 val64; - struct TxD *txdp; - struct TxFIFO_element __iomem *tx_fifo; + TxD_t *txdp; + TxFIFO_element_t __iomem *tx_fifo; unsigned long flags; u16 vlan_tag = 0; int vlan_priority = 0; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; int offload_type; @@ -3819,7 +3864,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) put_off = (u16) mac_control->fifos[queue].tx_curr_put_info.offset; get_off = (u16) mac_control->fifos[queue].tx_curr_get_info.offset; - txdp = (struct TxD *) mac_control->fifos[queue].list_info[put_off]. + txdp = (TxD_t *) mac_control->fifos[queue].list_info[put_off]. list_virt_addr; queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1; @@ -3842,10 +3887,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } offload_type = s2io_offload_type(skb); +#ifdef NETIF_F_TSO if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { txdp->Control_1 |= TXD_TCP_LSO_EN; txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb)); } +#endif if (skb->ip_summed == CHECKSUM_PARTIAL) { txdp->Control_2 |= (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN | @@ -3946,13 +3993,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) static void s2io_alarm_handle(unsigned long data) { - struct s2io_nic *sp = (struct s2io_nic *)data; + nic_t *sp = (nic_t *)data; alarm_intr_handler(sp); mod_timer(&sp->alarm_timer, jiffies + HZ / 2); } -static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n) +static int s2io_chk_rx_buffers(nic_t *sp, int rng_n) { int rxb_size, level; @@ -3984,9 +4031,9 @@ static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n) static irqreturn_t s2io_msi_handle(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; int i; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; atomic_inc(&sp->isr_cnt); @@ -4016,8 +4063,8 @@ static irqreturn_t s2io_msi_handle(int irq, void *dev_id) static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) { - struct ring_info *ring = (struct ring_info *)dev_id; - struct s2io_nic *sp = ring->nic; + ring_info_t *ring = (ring_info_t *)dev_id; + nic_t *sp = ring->nic; atomic_inc(&sp->isr_cnt); @@ -4030,17 +4077,17 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id) { - struct fifo_info *fifo = (struct fifo_info *)dev_id; - struct s2io_nic *sp = fifo->nic; + fifo_info_t *fifo = (fifo_info_t *)dev_id; + nic_t *sp = fifo->nic; atomic_inc(&sp->isr_cnt); tx_intr_handler(fifo); atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; } -static void s2io_txpic_intr_handle(struct s2io_nic *sp) +static void s2io_txpic_intr_handle(nic_t *sp) { - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; val64 = readq(&bar0->pic_int_status); @@ -4062,33 +4109,39 @@ static void s2io_txpic_intr_handle(struct s2io_nic *sp) } else if (val64 & GPIO_INT_REG_LINK_UP) { val64 = readq(&bar0->adapter_status); + if (verify_xena_quiescence(sp, val64, + sp->device_enabled_once)) { /* Enable Adapter */ - val64 = readq(&bar0->adapter_control); - val64 |= ADAPTER_CNTL_EN; - writeq(val64, &bar0->adapter_control); - val64 |= ADAPTER_LED_ON; - writeq(val64, &bar0->adapter_control); - if (!sp->device_enabled_once) - sp->device_enabled_once = 1; + val64 = readq(&bar0->adapter_control); + val64 |= ADAPTER_CNTL_EN; + writeq(val64, &bar0->adapter_control); + val64 |= ADAPTER_LED_ON; + writeq(val64, &bar0->adapter_control); + if (!sp->device_enabled_once) + sp->device_enabled_once = 1; - s2io_link(sp, LINK_UP); - /* - * unmask link down interrupt and mask link-up - * intr - */ - val64 = readq(&bar0->gpio_int_mask); - val64 &= ~GPIO_INT_MASK_LINK_DOWN; - val64 |= GPIO_INT_MASK_LINK_UP; - writeq(val64, &bar0->gpio_int_mask); + s2io_link(sp, LINK_UP); + /* + * unmask link down interrupt and mask link-up + * intr + */ + val64 = readq(&bar0->gpio_int_mask); + val64 &= ~GPIO_INT_MASK_LINK_DOWN; + val64 |= GPIO_INT_MASK_LINK_UP; + writeq(val64, &bar0->gpio_int_mask); + } }else if (val64 & GPIO_INT_REG_LINK_DOWN) { val64 = readq(&bar0->adapter_status); - s2io_link(sp, LINK_DOWN); - /* Link is down so unmaks link up interrupt */ - val64 = readq(&bar0->gpio_int_mask); - val64 &= ~GPIO_INT_MASK_LINK_UP; - val64 |= GPIO_INT_MASK_LINK_DOWN; - writeq(val64, &bar0->gpio_int_mask); + if (verify_xena_quiescence(sp, val64, + sp->device_enabled_once)) { + s2io_link(sp, LINK_DOWN); + /* Link is down so unmaks link up interrupt */ + val64 = readq(&bar0->gpio_int_mask); + val64 &= ~GPIO_INT_MASK_LINK_UP; + val64 |= GPIO_INT_MASK_LINK_DOWN; + writeq(val64, &bar0->gpio_int_mask); + } } } val64 = readq(&bar0->gpio_int_mask); @@ -4110,11 +4163,11 @@ static void s2io_txpic_intr_handle(struct s2io_nic *sp) static irqreturn_t s2io_isr(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; - struct s2io_nic *sp = dev->priv; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + nic_t *sp = dev->priv; + XENA_dev_config_t __iomem *bar0 = sp->bar0; int i; - u64 reason = 0; - struct mac_info *mac_control; + u64 reason = 0, val64, org_mask; + mac_info_t *mac_control; struct config_param *config; atomic_inc(&sp->isr_cnt); @@ -4132,48 +4185,43 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) reason = readq(&bar0->general_int_status); if (!reason) { - /* The interrupt was not raised by us. */ - atomic_dec(&sp->isr_cnt); - return IRQ_NONE; - } - else if (unlikely(reason == S2IO_MINUS_ONE) ) { - /* Disable device and get out */ + /* The interrupt was not raised by Xena. */ atomic_dec(&sp->isr_cnt); return IRQ_NONE; } - if (napi) { - if (reason & GEN_INTR_RXTRAFFIC) { - if ( likely ( netif_rx_schedule_prep(dev)) ) { - __netif_rx_schedule(dev); - writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask); - } - else - writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); - } - } else { - /* - * Rx handler is called by default, without checking for the - * cause of interrupt. - * rx_traffic_int reg is an R1 register, writing all 1's - * will ensure that the actual interrupt causing bit get's - * cleared and hence a read can be avoided. - */ - if (reason & GEN_INTR_RXTRAFFIC) - writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); + val64 = 0xFFFFFFFFFFFFFFFFULL; + /* Store current mask before masking all interrupts */ + org_mask = readq(&bar0->general_int_mask); + writeq(val64, &bar0->general_int_mask); - for (i = 0; i < config->rx_ring_num; i++) { - rx_intr_handler(&mac_control->rings[i]); +#ifdef CONFIG_S2IO_NAPI + if (reason & GEN_INTR_RXTRAFFIC) { + if (netif_rx_schedule_prep(dev)) { + writeq(val64, &bar0->rx_traffic_mask); + __netif_rx_schedule(dev); } } +#else + /* + * Rx handler is called by default, without checking for the + * cause of interrupt. + * rx_traffic_int reg is an R1 register, writing all 1's + * will ensure that the actual interrupt causing bit get's + * cleared and hence a read can be avoided. + */ + writeq(val64, &bar0->rx_traffic_int); + for (i = 0; i < config->rx_ring_num; i++) { + rx_intr_handler(&mac_control->rings[i]); + } +#endif /* * tx_traffic_int reg is an R1 register, writing all 1's * will ensure that the actual interrupt causing bit get's * cleared and hence a read can be avoided. */ - if (reason & GEN_INTR_TXTRAFFIC) - writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int); + writeq(val64, &bar0->tx_traffic_int); for (i = 0; i < config->tx_fifo_num; i++) tx_intr_handler(&mac_control->fifos[i]); @@ -4185,14 +4233,11 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) * reallocate the buffers from the interrupt handler itself, * else schedule a tasklet to reallocate the buffers. */ - if (!napi) { - for (i = 0; i < config->rx_ring_num; i++) - s2io_chk_rx_buffers(sp, i); - } - - writeq(0, &bar0->general_int_mask); - readl(&bar0->general_int_status); - +#ifndef CONFIG_S2IO_NAPI + for (i = 0; i < config->rx_ring_num; i++) + s2io_chk_rx_buffers(sp, i); +#endif + writeq(org_mask, &bar0->general_int_mask); atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; } @@ -4200,9 +4245,9 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) /** * s2io_updt_stats - */ -static void s2io_updt_stats(struct s2io_nic *sp) +static void s2io_updt_stats(nic_t *sp) { - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; int cnt = 0; @@ -4221,7 +4266,7 @@ static void s2io_updt_stats(struct s2io_nic *sp) break; /* Updt failed */ } while(1); } else { - memset(sp->mac_control.stats_info, 0, sizeof(struct stat_block)); + memset(sp->mac_control.stats_info, 0, sizeof(StatInfo_t)); } } @@ -4237,8 +4282,8 @@ static void s2io_updt_stats(struct s2io_nic *sp) static struct net_device_stats *s2io_get_stats(struct net_device *dev) { - struct s2io_nic *sp = dev->priv; - struct mac_info *mac_control; + nic_t *sp = dev->priv; + mac_info_t *mac_control; struct config_param *config; @@ -4279,8 +4324,8 @@ static void s2io_set_multicast(struct net_device *dev) { int i, j, prev_cnt; struct dev_mc_list *mclist; - struct s2io_nic *sp = dev->priv; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + nic_t *sp = dev->priv; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64 = 0, multi_mac = 0x010203040506ULL, mask = 0xfeffffffffffULL; u64 dis_addr = 0xffffffffffffULL, mac_addr = 0; @@ -4433,8 +4478,8 @@ static void s2io_set_multicast(struct net_device *dev) static int s2io_set_mac_addr(struct net_device *dev, u8 * addr) { - struct s2io_nic *sp = dev->priv; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + nic_t *sp = dev->priv; + XENA_dev_config_t __iomem *bar0 = sp->bar0; register u64 val64, mac_addr = 0; int i; @@ -4480,7 +4525,7 @@ static int s2io_set_mac_addr(struct net_device *dev, u8 * addr) static int s2io_ethtool_sset(struct net_device *dev, struct ethtool_cmd *info) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; if ((info->autoneg == AUTONEG_ENABLE) || (info->speed != SPEED_10000) || (info->duplex != DUPLEX_FULL)) return -EINVAL; @@ -4506,7 +4551,7 @@ static int s2io_ethtool_sset(struct net_device *dev, static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; info->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); info->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); info->port = PORT_FIBRE; @@ -4539,7 +4584,7 @@ static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info) static void s2io_ethtool_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; strncpy(info->driver, s2io_driver_name, sizeof(info->driver)); strncpy(info->version, s2io_driver_version, sizeof(info->version)); @@ -4571,7 +4616,7 @@ static void s2io_ethtool_gregs(struct net_device *dev, int i; u64 reg; u8 *reg_space = (u8 *) space; - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; regs->len = XENA_REG_SPACE; regs->version = sp->pdev->subsystem_device; @@ -4593,8 +4638,8 @@ static void s2io_ethtool_gregs(struct net_device *dev, */ static void s2io_phy_id(unsigned long data) { - struct s2io_nic *sp = (struct s2io_nic *) data; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + nic_t *sp = (nic_t *) data; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64 = 0; u16 subid; @@ -4631,8 +4676,8 @@ static void s2io_phy_id(unsigned long data) static int s2io_ethtool_idnic(struct net_device *dev, u32 data) { u64 val64 = 0, last_gpio_ctrl_val; - struct s2io_nic *sp = dev->priv; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + nic_t *sp = dev->priv; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u16 subid; subid = sp->pdev->subsystem_device; @@ -4680,8 +4725,8 @@ static void s2io_ethtool_getpause_data(struct net_device *dev, struct ethtool_pauseparam *ep) { u64 val64; - struct s2io_nic *sp = dev->priv; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + nic_t *sp = dev->priv; + XENA_dev_config_t __iomem *bar0 = sp->bar0; val64 = readq(&bar0->rmac_pause_cfg); if (val64 & RMAC_PAUSE_GEN_ENABLE) @@ -4707,8 +4752,8 @@ static int s2io_ethtool_setpause_data(struct net_device *dev, struct ethtool_pauseparam *ep) { u64 val64; - struct s2io_nic *sp = dev->priv; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + nic_t *sp = dev->priv; + XENA_dev_config_t __iomem *bar0 = sp->bar0; val64 = readq(&bar0->rmac_pause_cfg); if (ep->tx_pause) @@ -4740,12 +4785,12 @@ static int s2io_ethtool_setpause_data(struct net_device *dev, */ #define S2IO_DEV_ID 5 -static int read_eeprom(struct s2io_nic * sp, int off, u64 * data) +static int read_eeprom(nic_t * sp, int off, u64 * data) { int ret = -1; u32 exit_cnt = 0; u64 val64; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; if (sp->device_type == XFRAME_I_DEVICE) { val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) | @@ -4805,11 +4850,11 @@ static int read_eeprom(struct s2io_nic * sp, int off, u64 * data) * 0 on success, -1 on failure. */ -static int write_eeprom(struct s2io_nic * sp, int off, u64 data, int cnt) +static int write_eeprom(nic_t * sp, int off, u64 data, int cnt) { int exit_cnt = 0, ret = -1; u64 val64; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; if (sp->device_type == XFRAME_I_DEVICE) { val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) | @@ -4854,7 +4899,7 @@ static int write_eeprom(struct s2io_nic * sp, int off, u64 data, int cnt) } return ret; } -static void s2io_vpd_read(struct s2io_nic *nic) +static void s2io_vpd_read(nic_t *nic) { u8 *vpd_data; u8 data; @@ -4869,7 +4914,6 @@ static void s2io_vpd_read(struct s2io_nic *nic) strcpy(nic->product_name, "Xframe I 10GbE network adapter"); vpd_addr = 0x50; } - strcpy(nic->serial_num, "NOT AVAILABLE"); vpd_data = kmalloc(256, GFP_KERNEL); if (!vpd_data) @@ -4893,22 +4937,7 @@ static void s2io_vpd_read(struct s2io_nic *nic) pci_read_config_dword(nic->pdev, (vpd_addr + 4), (u32 *)&vpd_data[i]); } - - if(!fail) { - /* read serial number of adapter */ - for (cnt = 0; cnt < 256; cnt++) { - if ((vpd_data[cnt] == 'S') && - (vpd_data[cnt+1] == 'N') && - (vpd_data[cnt+2] < VPD_STRING_LEN)) { - memset(nic->serial_num, 0, VPD_STRING_LEN); - memcpy(nic->serial_num, &vpd_data[cnt + 3], - vpd_data[cnt+2]); - break; - } - } - } - - if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) { + if ((!fail) && (vpd_data[1] < VPD_PRODUCT_NAME_LEN)) { memset(nic->product_name, 0, vpd_data[1]); memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); } @@ -4933,7 +4962,7 @@ static int s2io_ethtool_geeprom(struct net_device *dev, { u32 i, valid; u64 data; - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; eeprom->magic = sp->pdev->vendor | (sp->pdev->device << 16); @@ -4971,7 +5000,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev, { int len = eeprom->len, cnt = 0; u64 valid = 0, data; - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; if (eeprom->magic != (sp->pdev->vendor | (sp->pdev->device << 16))) { DBG_PRINT(ERR_DBG, @@ -5015,9 +5044,9 @@ static int s2io_ethtool_seeprom(struct net_device *dev, * 0 on success. */ -static int s2io_register_test(struct s2io_nic * sp, uint64_t * data) +static int s2io_register_test(nic_t * sp, uint64_t * data) { - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64 = 0, exp_val; int fail = 0; @@ -5082,7 +5111,7 @@ static int s2io_register_test(struct s2io_nic * sp, uint64_t * data) * 0 on success. */ -static int s2io_eeprom_test(struct s2io_nic * sp, uint64_t * data) +static int s2io_eeprom_test(nic_t * sp, uint64_t * data) { int fail = 0; u64 ret_data, org_4F0, org_7F0; @@ -5184,7 +5213,7 @@ static int s2io_eeprom_test(struct s2io_nic * sp, uint64_t * data) * 0 on success and -1 on failure. */ -static int s2io_bist_test(struct s2io_nic * sp, uint64_t * data) +static int s2io_bist_test(nic_t * sp, uint64_t * data) { u8 bist = 0; int cnt = 0, ret = -1; @@ -5220,9 +5249,9 @@ static int s2io_bist_test(struct s2io_nic * sp, uint64_t * data) * 0 on success. */ -static int s2io_link_test(struct s2io_nic * sp, uint64_t * data) +static int s2io_link_test(nic_t * sp, uint64_t * data) { - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; val64 = readq(&bar0->adapter_status); @@ -5247,9 +5276,9 @@ static int s2io_link_test(struct s2io_nic * sp, uint64_t * data) * 0 on success. */ -static int s2io_rldram_test(struct s2io_nic * sp, uint64_t * data) +static int s2io_rldram_test(nic_t * sp, uint64_t * data) { - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; int cnt, iteration = 0, test_fail = 0; @@ -5351,7 +5380,7 @@ static void s2io_ethtool_test(struct net_device *dev, struct ethtool_test *ethtest, uint64_t * data) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; int orig_state = netif_running(sp->dev); if (ethtest->flags == ETH_TEST_FL_OFFLINE) { @@ -5407,8 +5436,8 @@ static void s2io_get_ethtool_stats(struct net_device *dev, u64 * tmp_stats) { int i = 0; - struct s2io_nic *sp = dev->priv; - struct stat_block *stat_info = sp->mac_control.stats_info; + nic_t *sp = dev->priv; + StatInfo_t *stat_info = sp->mac_control.stats_info; s2io_updt_stats(sp); tmp_stats[i++] = @@ -5635,14 +5664,14 @@ static int s2io_ethtool_get_regs_len(struct net_device *dev) static u32 s2io_ethtool_get_rx_csum(struct net_device * dev) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; return (sp->rx_csum); } static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; if (data) sp->rx_csum = 1; @@ -5721,8 +5750,10 @@ static const struct ethtool_ops netdev_ethtool_ops = { .set_tx_csum = s2io_ethtool_op_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO .get_tso = s2io_ethtool_op_get_tso, .set_tso = s2io_ethtool_op_set_tso, +#endif .get_ufo = ethtool_op_get_ufo, .set_ufo = ethtool_op_set_ufo, .self_test_count = s2io_ethtool_self_test_count, @@ -5763,7 +5794,7 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int s2io_change_mtu(struct net_device *dev, int new_mtu) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) { DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n", @@ -5782,7 +5813,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) if (netif_queue_stopped(dev)) netif_wake_queue(dev); } else { /* Device is down */ - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64 = new_mtu; writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); @@ -5807,9 +5838,9 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) static void s2io_tasklet(unsigned long dev_addr) { struct net_device *dev = (struct net_device *) dev_addr; - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; int i, ret; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; mac_control = &sp->mac_control; @@ -5842,9 +5873,9 @@ static void s2io_tasklet(unsigned long dev_addr) static void s2io_set_link(struct work_struct *work) { - struct s2io_nic *nic = container_of(work, struct s2io_nic, set_link_task); + nic_t *nic = container_of(work, nic_t, set_link_task); struct net_device *dev = nic->dev; - struct XENA_dev_config __iomem *bar0 = nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64; u16 subid; @@ -5863,53 +5894,57 @@ static void s2io_set_link(struct work_struct *work) } val64 = readq(&bar0->adapter_status); - if (LINK_IS_UP(val64)) { - if (!(readq(&bar0->adapter_control) & ADAPTER_CNTL_EN)) { - if (verify_xena_quiescence(nic)) { - val64 = readq(&bar0->adapter_control); - val64 |= ADAPTER_CNTL_EN; + if (verify_xena_quiescence(nic, val64, nic->device_enabled_once)) { + if (LINK_IS_UP(val64)) { + val64 = readq(&bar0->adapter_control); + val64 |= ADAPTER_CNTL_EN; + writeq(val64, &bar0->adapter_control); + if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type, + subid)) { + val64 = readq(&bar0->gpio_control); + val64 |= GPIO_CTRL_GPIO_0; + writeq(val64, &bar0->gpio_control); + val64 = readq(&bar0->gpio_control); + } else { + val64 |= ADAPTER_LED_ON; writeq(val64, &bar0->adapter_control); - if (CARDS_WITH_FAULTY_LINK_INDICATORS( - nic->device_type, subid)) { - val64 = readq(&bar0->gpio_control); - val64 |= GPIO_CTRL_GPIO_0; - writeq(val64, &bar0->gpio_control); - val64 = readq(&bar0->gpio_control); - } else { - val64 |= ADAPTER_LED_ON; - writeq(val64, &bar0->adapter_control); + } + if (s2io_link_fault_indication(nic) == + MAC_RMAC_ERR_TIMER) { + val64 = readq(&bar0->adapter_status); + if (!LINK_IS_UP(val64)) { + DBG_PRINT(ERR_DBG, "%s:", dev->name); + DBG_PRINT(ERR_DBG, " Link down"); + DBG_PRINT(ERR_DBG, "after "); + DBG_PRINT(ERR_DBG, "enabling "); + DBG_PRINT(ERR_DBG, "device \n"); } + } + if (nic->device_enabled_once == FALSE) { nic->device_enabled_once = TRUE; - } else { - DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name); - DBG_PRINT(ERR_DBG, "device is not Quiescent\n"); - netif_stop_queue(dev); } - } - val64 = readq(&bar0->adapter_status); - if (!LINK_IS_UP(val64)) { - DBG_PRINT(ERR_DBG, "%s:", dev->name); - DBG_PRINT(ERR_DBG, " Link down after enabling "); - DBG_PRINT(ERR_DBG, "device \n"); - } else s2io_link(nic, LINK_UP); - } else { - if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type, - subid)) { - val64 = readq(&bar0->gpio_control); - val64 &= ~GPIO_CTRL_GPIO_0; - writeq(val64, &bar0->gpio_control); - val64 = readq(&bar0->gpio_control); + } else { + if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type, + subid)) { + val64 = readq(&bar0->gpio_control); + val64 &= ~GPIO_CTRL_GPIO_0; + writeq(val64, &bar0->gpio_control); + val64 = readq(&bar0->gpio_control); + } + s2io_link(nic, LINK_DOWN); } - s2io_link(nic, LINK_DOWN); + } else { /* NIC is not Quiescent. */ + DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name); + DBG_PRINT(ERR_DBG, "device is not Quiescent\n"); + netif_stop_queue(dev); } clear_bit(0, &(nic->link_state)); } -static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, - struct buffAdd *ba, - struct sk_buff **skb, u64 *temp0, u64 *temp1, - u64 *temp2, int size) +static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba, + struct sk_buff **skb, u64 *temp0, u64 *temp1, + u64 *temp2, int size) { struct net_device *dev = sp->dev; struct sk_buff *frag_list; @@ -5923,7 +5958,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, * using same mapped address for the Rxd * buffer pointer */ - ((struct RxD1*)rxdp)->Buffer0_ptr = *temp0; + ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0; } else { *skb = dev_alloc_skb(size); if (!(*skb)) { @@ -5935,7 +5970,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, * such it will be used for next rxd whose * Host Control is NULL */ - ((struct RxD1*)rxdp)->Buffer0_ptr = *temp0 = + ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0 = pci_map_single( sp->pdev, (*skb)->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); @@ -5944,36 +5979,36 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) { /* Two buffer Mode */ if (*skb) { - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2; - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0; - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1; + ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2; + ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0; + ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1; } else { *skb = dev_alloc_skb(size); if (!(*skb)) { DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n", - dev->name); + dev->name); return -ENOMEM; } - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2 = + ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 = pci_map_single(sp->pdev, (*skb)->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0 = + ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 = pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); rxdp->Host_Control = (unsigned long) (*skb); /* Buffer-1 will be dummy buffer not used */ - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1 = + ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 = pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN, PCI_DMA_FROMDEVICE); } } else if ((rxdp->Host_Control == 0)) { /* Three buffer mode */ if (*skb) { - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0; - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1; - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2; + ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0; + ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1; + ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2; } else { *skb = dev_alloc_skb(size); if (!(*skb)) { @@ -5981,11 +6016,11 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, dev->name); return -ENOMEM; } - ((struct RxD3*)rxdp)->Buffer0_ptr = *temp0 = + ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 = pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); /* Buffer-1 receives L3/L4 headers */ - ((struct RxD3*)rxdp)->Buffer1_ptr = *temp1 = + ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 = pci_map_single( sp->pdev, (*skb)->data, l3l4hdr_size + 4, PCI_DMA_FROMDEVICE); @@ -6005,15 +6040,14 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, /* * Buffer-2 receives L4 data payload */ - ((struct RxD3*)rxdp)->Buffer2_ptr = *temp2 = + ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 = pci_map_single( sp->pdev, frag_list->data, dev->mtu, PCI_DMA_FROMDEVICE); } } return 0; } -static void set_rxd_buffer_size(struct s2io_nic *sp, struct RxD_t *rxdp, - int size) +static void set_rxd_buffer_size(nic_t *sp, RxD_t *rxdp, int size) { struct net_device *dev = sp->dev; if (sp->rxd_mode == RXD_MODE_1) { @@ -6029,15 +6063,15 @@ static void set_rxd_buffer_size(struct s2io_nic *sp, struct RxD_t *rxdp, } } -static int rxd_owner_bit_reset(struct s2io_nic *sp) +static int rxd_owner_bit_reset(nic_t *sp) { int i, j, k, blk_cnt = 0, size; - struct mac_info * mac_control = &sp->mac_control; + mac_info_t * mac_control = &sp->mac_control; struct config_param *config = &sp->config; struct net_device *dev = sp->dev; - struct RxD_t *rxdp = NULL; + RxD_t *rxdp = NULL; struct sk_buff *skb = NULL; - struct buffAdd *ba = NULL; + buffAdd_t *ba = NULL; u64 temp0_64 = 0, temp1_64 = 0, temp2_64 = 0; /* Calculate the size based on ring mode */ @@ -6076,7 +6110,7 @@ static int rxd_owner_bit_reset(struct s2io_nic *sp) } -static int s2io_add_isr(struct s2io_nic * sp) +static int s2io_add_isr(nic_t * sp) { int ret = 0; struct net_device *dev = sp->dev; @@ -6091,7 +6125,7 @@ static int s2io_add_isr(struct s2io_nic * sp) sp->intr_type = INTA; } - /* Store the values of the MSIX table in the struct s2io_nic structure */ + /* Store the values of the MSIX table in the nic_t structure */ store_xmsi_data(sp); /* After proper initialization of H/W, register ISR */ @@ -6146,7 +6180,7 @@ static int s2io_add_isr(struct s2io_nic * sp) } return 0; } -static void s2io_rem_isr(struct s2io_nic * sp) +static void s2io_rem_isr(nic_t * sp) { int cnt = 0; struct net_device *dev = sp->dev; @@ -6188,10 +6222,10 @@ static void s2io_rem_isr(struct s2io_nic * sp) } while(cnt < 5); } -static void s2io_card_down(struct s2io_nic * sp) +static void s2io_card_down(nic_t * sp) { int cnt = 0; - struct XENA_dev_config __iomem *bar0 = sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; unsigned long flags; register u64 val64 = 0; @@ -6222,8 +6256,7 @@ static void s2io_card_down(struct s2io_nic * sp) rxd_owner_bit_reset(sp); val64 = readq(&bar0->adapter_status); - if (verify_xena_quiescence(sp)) { - if(verify_pcc_quiescent(sp, sp->device_enabled_once)) + if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) { break; } @@ -6252,10 +6285,10 @@ static void s2io_card_down(struct s2io_nic * sp) clear_bit(0, &(sp->link_state)); } -static int s2io_card_up(struct s2io_nic * sp) +static int s2io_card_up(nic_t * sp) { int i, ret = 0; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; struct net_device *dev = (struct net_device *) sp->dev; u16 interruptible; @@ -6286,13 +6319,6 @@ static int s2io_card_up(struct s2io_nic * sp) DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i, atomic_read(&sp->rx_bufs_left[i])); } - /* Maintain the state prior to the open */ - if (sp->promisc_flg) - sp->promisc_flg = 0; - if (sp->m_cast_flg) { - sp->m_cast_flg = 0; - sp->all_multi_pos= 0; - } /* Setting its receive mode */ s2io_set_multicast(dev); @@ -6354,7 +6380,7 @@ static int s2io_card_up(struct s2io_nic * sp) static void s2io_restart_nic(struct work_struct *work) { - struct s2io_nic *sp = container_of(work, struct s2io_nic, rst_timer_task); + nic_t *sp = container_of(work, nic_t, rst_timer_task); struct net_device *dev = sp->dev; s2io_card_down(sp); @@ -6383,7 +6409,7 @@ static void s2io_restart_nic(struct work_struct *work) static void s2io_tx_watchdog(struct net_device *dev) { - struct s2io_nic *sp = dev->priv; + nic_t *sp = dev->priv; if (netif_carrier_ok(dev)) { schedule_work(&sp->rst_timer_task); @@ -6408,16 +6434,16 @@ static void s2io_tx_watchdog(struct net_device *dev) * Return value: * SUCCESS on success and -1 on failure. */ -static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) +static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) { - struct s2io_nic *sp = ring_data->nic; + nic_t *sp = ring_data->nic; struct net_device *dev = (struct net_device *) sp->dev; struct sk_buff *skb = (struct sk_buff *) ((unsigned long) rxdp->Host_Control); int ring_no = ring_data->ring_no; u16 l3_csum, l4_csum; unsigned long long err = rxdp->Control_1 & RXD_T_CODE; - struct lro *lro; + lro_t *lro; skb->dev = dev; @@ -6462,7 +6488,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) int buf2_len = RXD_GET_BUFFER2_SIZE_3(rxdp->Control_2); unsigned char *buff = skb_push(skb, buf0_len); - struct buffAdd *ba = &ring_data->ba[get_block][get_off]; + buffAdd_t *ba = &ring_data->ba[get_block][get_off]; sp->stats.rx_bytes += buf0_len + buf2_len; memcpy(buff, ba->ba_0, buf0_len); @@ -6472,6 +6498,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) skb_put(skb, buf1_len); skb->len += buf2_len; skb->data_len += buf2_len; + skb->truesize += buf2_len; skb_put(skb_shinfo(skb)->frag_list, buf2_len); sp->stats.rx_bytes += buf1_len; @@ -6555,20 +6582,23 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) if (!sp->lro) { skb->protocol = eth_type_trans(skb, dev); +#ifdef CONFIG_S2IO_NAPI if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { /* Queueing the vlan frame to the upper layer */ - if (napi) - vlan_hwaccel_receive_skb(skb, sp->vlgrp, - RXD_GET_VLAN_TAG(rxdp->Control_2)); - else - vlan_hwaccel_rx(skb, sp->vlgrp, - RXD_GET_VLAN_TAG(rxdp->Control_2)); + vlan_hwaccel_receive_skb(skb, sp->vlgrp, + RXD_GET_VLAN_TAG(rxdp->Control_2)); } else { - if (napi) - netif_receive_skb(skb); - else - netif_rx(skb); + netif_receive_skb(skb); } +#else + if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { + /* Queueing the vlan frame to the upper layer */ + vlan_hwaccel_rx(skb, sp->vlgrp, + RXD_GET_VLAN_TAG(rxdp->Control_2)); + } else { + netif_rx(skb); + } +#endif } else { send_up: queue_rx_frame(skb); @@ -6592,7 +6622,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) * void. */ -static void s2io_link(struct s2io_nic * sp, int link) +static void s2io_link(nic_t * sp, int link) { struct net_device *dev = (struct net_device *) sp->dev; @@ -6636,7 +6666,7 @@ static int get_xena_rev_id(struct pci_dev *pdev) * void */ -static void s2io_init_pci(struct s2io_nic * sp) +static void s2io_init_pci(nic_t * sp) { u16 pci_cmd = 0, pcix_cmd = 0; @@ -6669,9 +6699,13 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) DBG_PRINT(ERR_DBG, "s2io: Default to 8 Rx rings\n"); rx_ring_num = 8; } - if (*dev_intr_type != INTA) - napi = 0; - +#ifdef CONFIG_S2IO_NAPI + if (*dev_intr_type != INTA) { + DBG_PRINT(ERR_DBG, "s2io: NAPI cannot be enabled when " + "MSI/MSI-X is enabled. Defaulting to INTA\n"); + *dev_intr_type = INTA; + } +#endif #ifndef CONFIG_PCI_MSI if (*dev_intr_type != INTA) { DBG_PRINT(ERR_DBG, "s2io: This kernel does not support" @@ -6692,8 +6726,6 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) "Defaulting to INTA\n"); *dev_intr_type = INTA; } - if ( (rx_ring_num > 1) && (*dev_intr_type != INTA) ) - napi = 0; if (rx_ring_mode > 3) { DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n"); DBG_PRINT(ERR_DBG, "s2io: Defaulting to 3-buffer mode\n"); @@ -6719,15 +6751,15 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) static int __devinit s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) { - struct s2io_nic *sp; + nic_t *sp; struct net_device *dev; int i, j, ret; int dma_flag = FALSE; u32 mac_up, mac_down; u64 val64 = 0, tmp64 = 0; - struct XENA_dev_config __iomem *bar0 = NULL; + XENA_dev_config_t __iomem *bar0 = NULL; u16 subid; - struct mac_info *mac_control; + mac_info_t *mac_control; struct config_param *config; int mode; u8 dev_intr_type = intr_type; @@ -6782,7 +6814,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) } } - dev = alloc_etherdev(sizeof(struct s2io_nic)); + dev = alloc_etherdev(sizeof(nic_t)); if (dev == NULL) { DBG_PRINT(ERR_DBG, "Device allocation failed\n"); pci_disable_device(pdev); @@ -6797,7 +6829,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* Private member variable initialized to s2io NIC structure */ sp = dev->priv; - memset(sp, 0, sizeof(struct s2io_nic)); + memset(sp, 0, sizeof(nic_t)); sp->dev = dev; sp->pdev = pdev; sp->high_dma_flag = dma_flag; @@ -6893,7 +6925,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) sp->bar0 = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!sp->bar0) { - DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem1\n", + DBG_PRINT(ERR_DBG, "%s: S2IO: cannot remap io mem1\n", dev->name); ret = -ENOMEM; goto bar0_remap_failed; @@ -6902,7 +6934,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) sp->bar1 = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); if (!sp->bar1) { - DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem2\n", + DBG_PRINT(ERR_DBG, "%s: S2IO: cannot remap io mem2\n", dev->name); ret = -ENOMEM; goto bar1_remap_failed; @@ -6913,7 +6945,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* Initializing the BAR1 address as the start of the FIFO pointer. */ for (j = 0; j < MAX_TX_FIFOS; j++) { - mac_control->tx_FIFO_start[j] = (struct TxFIFO_element __iomem *) + mac_control->tx_FIFO_start[j] = (TxFIFO_element_t __iomem *) (sp->bar1 + (j * 0x00020000)); } @@ -6934,8 +6966,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) * will use eth_mac_addr() for dev->set_mac_address * mac address will be set every time dev->open() is called */ +#if defined(CONFIG_S2IO_NAPI) dev->poll = s2io_poll; dev->weight = 32; +#endif #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = s2io_netpoll; @@ -6944,9 +6978,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; if (sp->high_dma_flag == TRUE) dev->features |= NETIF_F_HIGHDMA; +#ifdef NETIF_F_TSO dev->features |= NETIF_F_TSO; +#endif +#ifdef NETIF_F_TSO6 dev->features |= NETIF_F_TSO6; - if ((sp->device_type & XFRAME_II_DEVICE) && (ufo)) { +#endif + if (sp->device_type & XFRAME_II_DEVICE) { dev->features |= NETIF_F_UFO; dev->features |= NETIF_F_HW_CSUM; } @@ -7027,9 +7065,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* Initialize spinlocks */ spin_lock_init(&sp->tx_lock); - - if (!napi) - spin_lock_init(&sp->put_lock); +#ifndef CONFIG_S2IO_NAPI + spin_lock_init(&sp->put_lock); +#endif spin_lock_init(&sp->rx_lock); /* @@ -7060,14 +7098,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name, s2io_driver_version); DBG_PRINT(ERR_DBG, "%s: MAC ADDR: " - "%02x:%02x:%02x:%02x:%02x:%02x", dev->name, + "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, sp->def_mac_addr[0].mac_addr[0], sp->def_mac_addr[0].mac_addr[1], sp->def_mac_addr[0].mac_addr[2], sp->def_mac_addr[0].mac_addr[3], sp->def_mac_addr[0].mac_addr[4], sp->def_mac_addr[0].mac_addr[5]); - DBG_PRINT(ERR_DBG, "SERIAL NUMBER: %s\n", sp->serial_num); if (sp->device_type & XFRAME_II_DEVICE) { mode = s2io_print_pci_mode(sp); if (mode < 0) { @@ -7091,9 +7128,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->name); break; } - - if (napi) - DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name); +#ifdef CONFIG_S2IO_NAPI + DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name); +#endif switch(sp->intr_type) { case INTA: DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name); @@ -7108,9 +7145,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) if (sp->lro) DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n", dev->name); - if (ufo) - DBG_PRINT(ERR_DBG, "%s: UDP Fragmentation Offload(UFO)" - " enabled\n", dev->name); + /* Initialize device name */ sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name); @@ -7167,7 +7202,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev) { struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev); - struct s2io_nic *sp; + nic_t *sp; if (dev == NULL) { DBG_PRINT(ERR_DBG, "Driver Data is NULL!!\n"); @@ -7180,6 +7215,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev) free_shared_mem(sp); iounmap(sp->bar0); iounmap(sp->bar1); + pci_disable_device(pdev); if (sp->intr_type != MSI_X) pci_release_regions(pdev); else { @@ -7190,7 +7226,6 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev) } pci_set_drvdata(pdev, NULL); free_netdev(dev); - pci_disable_device(pdev); } /** @@ -7209,7 +7244,7 @@ int __init s2io_starter(void) * Description: This function is the cleanup routine for the driver. It unregist * ers the driver. */ -static __exit void s2io_closer(void) +static void s2io_closer(void) { pci_unregister_driver(&s2io_driver); DBG_PRINT(INIT_DBG, "cleanup done\n"); @@ -7219,7 +7254,7 @@ module_init(s2io_starter); module_exit(s2io_closer); static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, - struct tcphdr **tcp, struct RxD_t *rxdp) + struct tcphdr **tcp, RxD_t *rxdp) { int ip_off; u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len; @@ -7253,7 +7288,7 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, return 0; } -static int check_for_socket_match(struct lro *lro, struct iphdr *ip, +static int check_for_socket_match(lro_t *lro, struct iphdr *ip, struct tcphdr *tcp) { DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); @@ -7268,7 +7303,7 @@ static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp) return(ntohs(ip->tot_len) - (ip->ihl << 2) - (tcp->doff << 2)); } -static void initiate_new_session(struct lro *lro, u8 *l2h, +static void initiate_new_session(lro_t *lro, u8 *l2h, struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len) { DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); @@ -7294,12 +7329,12 @@ static void initiate_new_session(struct lro *lro, u8 *l2h, lro->in_use = 1; } -static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro) +static void update_L3L4_header(nic_t *sp, lro_t *lro) { struct iphdr *ip = lro->iph; struct tcphdr *tcp = lro->tcph; u16 nchk; - struct stat_block *statinfo = sp->mac_control.stats_info; + StatInfo_t *statinfo = sp->mac_control.stats_info; DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); /* Update L3 header */ @@ -7325,7 +7360,7 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro) statinfo->sw_stat.num_aggregations++; } -static void aggregate_new_rx(struct lro *lro, struct iphdr *ip, +static void aggregate_new_rx(lro_t *lro, struct iphdr *ip, struct tcphdr *tcp, u32 l4_pyld) { DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); @@ -7347,7 +7382,7 @@ static void aggregate_new_rx(struct lro *lro, struct iphdr *ip, } } -static int verify_l3_l4_lro_capable(struct lro *l_lro, struct iphdr *ip, +static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len) { u8 *ptr; @@ -7405,8 +7440,8 @@ static int verify_l3_l4_lro_capable(struct lro *l_lro, struct iphdr *ip, } static int -s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro, - struct RxD_t *rxdp, struct s2io_nic *sp) +s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro, + RxD_t *rxdp, nic_t *sp) { struct iphdr *ip; struct tcphdr *tcph; @@ -7423,7 +7458,7 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro, tcph = (struct tcphdr *)*tcp; *tcp_len = get_l4_pyld_length(ip, tcph); for (i=0; ilro0_n[i]; + lro_t *l_lro = &sp->lro0_n[i]; if (l_lro->in_use) { if (check_for_socket_match(l_lro, ip, tcph)) continue; @@ -7461,7 +7496,7 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro, } for (i=0; ilro0_n[i]; + lro_t *l_lro = &sp->lro0_n[i]; if (!(l_lro->in_use)) { *lro = l_lro; ret = 3; /* Begin anew */ @@ -7500,9 +7535,9 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro, return ret; } -static void clear_lro_session(struct lro *lro) +static void clear_lro_session(lro_t *lro) { - static u16 lro_struct_size = sizeof(struct lro); + static u16 lro_struct_size = sizeof(lro_t); memset(lro, 0, lro_struct_size); } @@ -7512,14 +7547,14 @@ static void queue_rx_frame(struct sk_buff *skb) struct net_device *dev = skb->dev; skb->protocol = eth_type_trans(skb, dev); - if (napi) - netif_receive_skb(skb); - else - netif_rx(skb); +#ifdef CONFIG_S2IO_NAPI + netif_receive_skb(skb); +#else + netif_rx(skb); +#endif } -static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, - struct sk_buff *skb, +static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len) { struct sk_buff *first = lro->parent; @@ -7531,7 +7566,6 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, lro->last_frag->next = skb; else skb_shinfo(first)->frag_list = skb; - first->truesize += skb->truesize; lro->last_frag = skb; sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++; return; diff --git a/trunk/drivers/net/s2io.h b/trunk/drivers/net/s2io.h index a5e1a513deb5..3b0bafd273c8 100644 --- a/trunk/drivers/net/s2io.h +++ b/trunk/drivers/net/s2io.h @@ -30,8 +30,6 @@ #undef SUCCESS #define SUCCESS 0 #define FAILURE -1 -#define S2IO_MINUS_ONE 0xFFFFFFFFFFFFFFFFULL -#define S2IO_MAX_PCI_CONFIG_SPACE_REINIT 100 #define CHECKBIT(value, nbit) (value & (1 << nbit)) @@ -39,7 +37,7 @@ #define MAX_FLICKER_TIME 60000 /* 60 Secs */ /* Maximum outstanding splits to be configured into xena. */ -enum { +typedef enum xena_max_outstanding_splits { XENA_ONE_SPLIT_TRANSACTION = 0, XENA_TWO_SPLIT_TRANSACTION = 1, XENA_THREE_SPLIT_TRANSACTION = 2, @@ -48,7 +46,7 @@ enum { XENA_TWELVE_SPLIT_TRANSACTION = 5, XENA_SIXTEEN_SPLIT_TRANSACTION = 6, XENA_THIRTYTWO_SPLIT_TRANSACTION = 7 -}; +} xena_max_outstanding_splits; #define XENA_MAX_OUTSTANDING_SPLITS(n) (n << 4) /* OS concerned variables and constants */ @@ -79,7 +77,7 @@ static int debug_level = ERR_DBG; #define S2IO_JUMBO_SIZE 9600 /* Driver statistics maintained by driver */ -struct swStat { +typedef struct { unsigned long long single_ecc_errs; unsigned long long double_ecc_errs; unsigned long long parity_err_cnt; @@ -94,10 +92,10 @@ struct swStat { unsigned long long flush_max_pkts; unsigned long long sum_avg_pkts_aggregated; unsigned long long num_aggregations; -}; +} swStat_t; /* Xpak releated alarm and warnings */ -struct xpakStat { +typedef struct { u64 alarm_transceiver_temp_high; u64 alarm_transceiver_temp_low; u64 alarm_laser_bias_current_high; @@ -112,11 +110,11 @@ struct xpakStat { u64 warn_laser_output_power_low; u64 xpak_regs_stat; u32 xpak_timer_count; -}; +} xpakStat_t; /* The statistics block of Xena */ -struct stat_block { +typedef struct stat_block { /* Tx MAC statistics counters. */ __le32 tmac_data_octets; __le32 tmac_frms; @@ -292,9 +290,9 @@ struct stat_block { __le32 reserved_14; __le32 link_fault_cnt; u8 buffer[20]; - struct swStat sw_stat; - struct xpakStat xpak_stat; -}; + swStat_t sw_stat; + xpakStat_t xpak_stat; +} StatInfo_t; /* * Structures representing different init time configuration @@ -317,7 +315,7 @@ static int fifo_map[][MAX_TX_FIFOS] = { }; /* Maintains Per FIFO related information. */ -struct tx_fifo_config { +typedef struct tx_fifo_config { #define MAX_AVAILABLE_TXDS 8192 u32 fifo_len; /* specifies len of FIFO upto 8192, ie no of TxDLs */ /* Priority definition */ @@ -334,11 +332,11 @@ struct tx_fifo_config { u8 f_no_snoop; #define NO_SNOOP_TXD 0x01 #define NO_SNOOP_TXD_BUFFER 0x02 -}; +} tx_fifo_config_t; /* Maintains per Ring related information */ -struct rx_ring_config { +typedef struct rx_ring_config { u32 num_rxd; /*No of RxDs per Rx Ring */ #define RX_RING_PRI_0 0 /* highest */ #define RX_RING_PRI_1 1 @@ -359,7 +357,7 @@ struct rx_ring_config { u8 f_no_snoop; #define NO_SNOOP_RXD 0x01 #define NO_SNOOP_RXD_BUFFER 0x02 -}; +} rx_ring_config_t; /* This structure provides contains values of the tunable parameters * of the H/W @@ -369,7 +367,7 @@ struct config_param { u32 tx_fifo_num; /*Number of Tx FIFOs */ u8 fifo_mapping[MAX_TX_FIFOS]; - struct tx_fifo_config tx_cfg[MAX_TX_FIFOS]; /*Per-Tx FIFO config */ + tx_fifo_config_t tx_cfg[MAX_TX_FIFOS]; /*Per-Tx FIFO config */ u32 max_txds; /*Max no. of Tx buffer descriptor per TxDL */ u64 tx_intr_type; /* Specifies if Tx Intr is UTILZ or PER_LIST type. */ @@ -378,7 +376,7 @@ struct config_param { u32 rx_ring_num; /*Number of receive rings */ #define MAX_RX_BLOCKS_PER_RING 150 - struct rx_ring_config rx_cfg[MAX_RX_RINGS]; /*Per-Rx Ring config */ + rx_ring_config_t rx_cfg[MAX_RX_RINGS]; /*Per-Rx Ring config */ u8 bimodal; /*Flag for setting bimodal interrupts*/ #define HEADER_ETHERNET_II_802_3_SIZE 14 @@ -397,14 +395,14 @@ struct config_param { }; /* Structure representing MAC Addrs */ -struct mac_addr { +typedef struct mac_addr { u8 mac_addr[ETH_ALEN]; -}; +} macaddr_t; /* Structure that represent every FIFO element in the BAR1 * Address location. */ -struct TxFIFO_element { +typedef struct _TxFIFO_element { u64 TxDL_Pointer; u64 List_Control; @@ -415,10 +413,10 @@ struct TxFIFO_element { #define TX_FIFO_SPECIAL_FUNC BIT(23) #define TX_FIFO_DS_NO_SNOOP BIT(31) #define TX_FIFO_BUFF_NO_SNOOP BIT(30) -}; +} TxFIFO_element_t; /* Tx descriptor structure */ -struct TxD { +typedef struct _TxD { u64 Control_1; /* bit mask */ #define TXD_LIST_OWN_XENA BIT(7) @@ -449,16 +447,16 @@ struct TxD { u64 Buffer_Pointer; u64 Host_Control; /* reserved for host */ -}; +} TxD_t; /* Structure to hold the phy and virt addr of every TxDL. */ -struct list_info_hold { +typedef struct list_info_hold { dma_addr_t list_phy_addr; void *list_virt_addr; -}; +} list_info_hold_t; /* Rx descriptor structure for 1 buffer mode */ -struct RxD_t { +typedef struct _RxD_t { u64 Host_Control; /* reserved for host */ u64 Control_1; #define RXD_OWN_XENA BIT(7) @@ -483,21 +481,21 @@ struct RxD_t { #define SET_NUM_TAG(val) vBIT(val,16,32) -}; +} RxD_t; /* Rx descriptor structure for 1 buffer mode */ -struct RxD1 { - struct RxD_t h; +typedef struct _RxD1_t { + struct _RxD_t h; #define MASK_BUFFER0_SIZE_1 vBIT(0x3FFF,2,14) #define SET_BUFFER0_SIZE_1(val) vBIT(val,2,14) #define RXD_GET_BUFFER0_SIZE_1(_Control_2) \ (u16)((_Control_2 & MASK_BUFFER0_SIZE_1) >> 48) u64 Buffer0_ptr; -}; +} RxD1_t; /* Rx descriptor structure for 3 or 2 buffer mode */ -struct RxD3 { - struct RxD_t h; +typedef struct _RxD3_t { + struct _RxD_t h; #define MASK_BUFFER0_SIZE_3 vBIT(0xFF,2,14) #define MASK_BUFFER1_SIZE_3 vBIT(0xFFFF,16,16) @@ -517,15 +515,15 @@ struct RxD3 { u64 Buffer0_ptr; u64 Buffer1_ptr; u64 Buffer2_ptr; -}; +} RxD3_t; /* Structure that represents the Rx descriptor block which contains * 128 Rx descriptors. */ -struct RxD_block { +typedef struct _RxD_block { #define MAX_RXDS_PER_BLOCK_1 127 - struct RxD1 rxd[MAX_RXDS_PER_BLOCK_1]; + RxD1_t rxd[MAX_RXDS_PER_BLOCK_1]; u64 reserved_0; #define END_OF_BLOCK 0xFEFFFFFFFFFFFFFFULL @@ -535,22 +533,22 @@ struct RxD_block { u64 pNext_RxD_Blk_physical; /* Buff0_ptr.In a 32 bit arch * the upper 32 bits should * be 0 */ -}; +} RxD_block_t; #define SIZE_OF_BLOCK 4096 -#define RXD_MODE_1 0 /* One Buffer mode */ -#define RXD_MODE_3A 1 /* Three Buffer mode */ -#define RXD_MODE_3B 2 /* Two Buffer mode */ +#define RXD_MODE_1 0 +#define RXD_MODE_3A 1 +#define RXD_MODE_3B 2 /* Structure to hold virtual addresses of Buf0 and Buf1 in * 2buf mode. */ -struct buffAdd { +typedef struct bufAdd { void *ba_0_org; void *ba_1_org; void *ba_0; void *ba_1; -}; +} buffAdd_t; /* Structure which stores all the MAC control parameters */ @@ -558,46 +556,43 @@ struct buffAdd { * from which the Rx Interrupt processor can start picking * up the RxDs for processing. */ -struct rx_curr_get_info { +typedef struct _rx_curr_get_info_t { u32 block_index; u32 offset; u32 ring_len; -}; +} rx_curr_get_info_t; -struct rx_curr_put_info { - u32 block_index; - u32 offset; - u32 ring_len; -}; +typedef rx_curr_get_info_t rx_curr_put_info_t; /* This structure stores the offset of the TxDl in the FIFO * from which the Tx Interrupt processor can start picking * up the TxDLs for send complete interrupt processing. */ -struct tx_curr_get_info { +typedef struct { u32 offset; u32 fifo_len; -}; +} tx_curr_get_info_t; -struct tx_curr_put_info { - u32 offset; - u32 fifo_len; -}; +typedef tx_curr_get_info_t tx_curr_put_info_t; -struct rxd_info { + +typedef struct rxd_info { void *virt_addr; dma_addr_t dma_addr; -}; +}rxd_info_t; /* Structure that holds the Phy and virt addresses of the Blocks */ -struct rx_block_info { +typedef struct rx_block_info { void *block_virt_addr; dma_addr_t block_dma_addr; - struct rxd_info *rxds; -}; + rxd_info_t *rxds; +} rx_block_info_t; + +/* pre declaration of the nic structure */ +typedef struct s2io_nic nic_t; /* Ring specific structure */ -struct ring_info { +typedef struct ring_info { /* The ring number */ int ring_no; @@ -605,7 +600,7 @@ struct ring_info { * Place holders for the virtual and physical addresses of * all the Rx Blocks */ - struct rx_block_info rx_blocks[MAX_RX_BLOCKS_PER_RING]; + rx_block_info_t rx_blocks[MAX_RX_BLOCKS_PER_RING]; int block_count; int pkt_cnt; @@ -613,24 +608,26 @@ struct ring_info { * Put pointer info which indictes which RxD has to be replenished * with a new buffer. */ - struct rx_curr_put_info rx_curr_put_info; + rx_curr_put_info_t rx_curr_put_info; /* * Get pointer info which indictes which is the last RxD that was * processed by the driver. */ - struct rx_curr_get_info rx_curr_get_info; + rx_curr_get_info_t rx_curr_get_info; +#ifndef CONFIG_S2IO_NAPI /* Index to the absolute position of the put pointer of Rx ring */ int put_pos; +#endif /* Buffer Address store. */ - struct buffAdd **ba; - struct s2io_nic *nic; -}; + buffAdd_t **ba; + nic_t *nic; +} ring_info_t; /* Fifo specific structure */ -struct fifo_info { +typedef struct fifo_info { /* FIFO number */ int fifo_no; @@ -638,40 +635,40 @@ struct fifo_info { int max_txds; /* Place holder of all the TX List's Phy and Virt addresses. */ - struct list_info_hold *list_info; + list_info_hold_t *list_info; /* * Current offset within the tx FIFO where driver would write * new Tx frame */ - struct tx_curr_put_info tx_curr_put_info; + tx_curr_put_info_t tx_curr_put_info; /* * Current offset within tx FIFO from where the driver would start freeing * the buffers */ - struct tx_curr_get_info tx_curr_get_info; + tx_curr_get_info_t tx_curr_get_info; - struct s2io_nic *nic; -}; + nic_t *nic; +}fifo_info_t; /* Information related to the Tx and Rx FIFOs and Rings of Xena * is maintained in this structure. */ -struct mac_info { +typedef struct mac_info { /* tx side stuff */ /* logical pointer of start of each Tx FIFO */ - struct TxFIFO_element __iomem *tx_FIFO_start[MAX_TX_FIFOS]; + TxFIFO_element_t __iomem *tx_FIFO_start[MAX_TX_FIFOS]; /* Fifo specific structure */ - struct fifo_info fifos[MAX_TX_FIFOS]; + fifo_info_t fifos[MAX_TX_FIFOS]; /* Save virtual address of TxD page with zero DMA addr(if any) */ void *zerodma_virt_addr; /* rx side stuff */ /* Ring specific structure */ - struct ring_info rings[MAX_RX_RINGS]; + ring_info_t rings[MAX_RX_RINGS]; u16 rmac_pause_time; u16 mc_pause_threshold_q0q3; @@ -680,14 +677,14 @@ struct mac_info { void *stats_mem; /* orignal pointer to allocated mem */ dma_addr_t stats_mem_phy; /* Physical address of the stat block */ u32 stats_mem_sz; - struct stat_block *stats_info; /* Logical address of the stat block */ -}; + StatInfo_t *stats_info; /* Logical address of the stat block */ +} mac_info_t; /* structure representing the user defined MAC addresses */ -struct usr_addr { +typedef struct { char addr[ETH_ALEN]; int usage_cnt; -}; +} usr_addr_t; /* Default Tunable parameters of the NIC. */ #define DEFAULT_FIFO_0_LEN 4096 @@ -720,7 +717,7 @@ struct msix_info_st { }; /* Data structure to represent a LRO session */ -struct lro { +typedef struct lro { struct sk_buff *parent; struct sk_buff *last_frag; u8 *l2h; @@ -736,18 +733,20 @@ struct lro { u32 cur_tsval; u32 cur_tsecr; u8 saw_ts; -}; +}lro_t; /* Structure representing one instance of the NIC */ struct s2io_nic { int rxd_mode; +#ifdef CONFIG_S2IO_NAPI /* * Count of packets to be processed in a given iteration, it will be indicated * by the quota field of the device structure when NAPI is enabled. */ int pkts_to_process; +#endif struct net_device *dev; - struct mac_info mac_control; + mac_info_t mac_control; struct config_param config; struct pci_dev *pdev; void __iomem *bar0; @@ -755,8 +754,8 @@ struct s2io_nic { #define MAX_MAC_SUPPORTED 16 #define MAX_SUPPORTED_MULTICASTS MAX_MAC_SUPPORTED - struct mac_addr def_mac_addr[MAX_MAC_SUPPORTED]; - struct mac_addr pre_mac_addr[MAX_MAC_SUPPORTED]; + macaddr_t def_mac_addr[MAX_MAC_SUPPORTED]; + macaddr_t pre_mac_addr[MAX_MAC_SUPPORTED]; struct net_device_stats stats; int high_dma_flag; @@ -776,7 +775,9 @@ struct s2io_nic { atomic_t rx_bufs_left[MAX_RX_RINGS]; spinlock_t tx_lock; +#ifndef CONFIG_S2IO_NAPI spinlock_t put_lock; +#endif #define PROMISC 1 #define ALL_MULTI 2 @@ -784,7 +785,7 @@ struct s2io_nic { #define MAX_ADDRS_SUPPORTED 64 u16 usr_addr_count; u16 mc_addr_count; - struct usr_addr usr_addrs[MAX_ADDRS_SUPPORTED]; + usr_addr_t usr_addrs[MAX_ADDRS_SUPPORTED]; u16 m_cast_flg; u16 all_multi_pos; @@ -840,7 +841,7 @@ struct s2io_nic { u8 device_type; #define MAX_LRO_SESSIONS 32 - struct lro lro0_n[MAX_LRO_SESSIONS]; + lro_t lro0_n[MAX_LRO_SESSIONS]; unsigned long clubbed_frms_cnt; unsigned long sending_both; u8 lro; @@ -854,9 +855,8 @@ struct s2io_nic { spinlock_t rx_lock; atomic_t isr_cnt; u64 *ufo_in_band_v; -#define VPD_STRING_LEN 80 - u8 product_name[VPD_STRING_LEN]; - u8 serial_num[VPD_STRING_LEN]; +#define VPD_PRODUCT_NAME_LEN 50 + u8 product_name[VPD_PRODUCT_NAME_LEN]; }; #define RESET_ERROR 1; @@ -975,50 +975,43 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev); static int init_shared_mem(struct s2io_nic *sp); static void free_shared_mem(struct s2io_nic *sp); static int init_nic(struct s2io_nic *nic); -static void rx_intr_handler(struct ring_info *ring_data); -static void tx_intr_handler(struct fifo_info *fifo_data); +static void rx_intr_handler(ring_info_t *ring_data); +static void tx_intr_handler(fifo_info_t *fifo_data); static void alarm_intr_handler(struct s2io_nic *sp); static int s2io_starter(void); -static void s2io_closer(void); static void s2io_tx_watchdog(struct net_device *dev); static void s2io_tasklet(unsigned long dev_addr); static void s2io_set_multicast(struct net_device *dev); -static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp); -static void s2io_link(struct s2io_nic * sp, int link); -static void s2io_reset(struct s2io_nic * sp); +static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp); +static void s2io_link(nic_t * sp, int link); +#if defined(CONFIG_S2IO_NAPI) static int s2io_poll(struct net_device *dev, int *budget); -static void s2io_init_pci(struct s2io_nic * sp); +#endif +static void s2io_init_pci(nic_t * sp); static int s2io_set_mac_addr(struct net_device *dev, u8 * addr); static void s2io_alarm_handle(unsigned long data); -static int s2io_enable_msi(struct s2io_nic *nic); +static int s2io_enable_msi(nic_t *nic); static irqreturn_t s2io_msi_handle(int irq, void *dev_id); static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id); static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id); static irqreturn_t s2io_isr(int irq, void *dev_id); -static int verify_xena_quiescence(struct s2io_nic *sp); +static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag); static const struct ethtool_ops netdev_ethtool_ops; static void s2io_set_link(struct work_struct *work); -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 s2io_set_swapper(nic_t * sp); +static void s2io_card_down(nic_t *nic); +static int s2io_card_up(nic_t *nic); static int get_xena_rev_id(struct pci_dev *pdev); -static int wait_for_cmd_complete(void *addr, u64 busy_bit); -static int s2io_add_isr(struct s2io_nic * sp); -static void s2io_rem_isr(struct s2io_nic * sp); - -static void restore_xmsi_data(struct s2io_nic *nic); +static void restore_xmsi_data(nic_t *nic); -static int -s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro, - struct RxD_t *rxdp, struct s2io_nic *sp); -static void clear_lro_session(struct lro *lro); +static int s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro, RxD_t *rxdp, nic_t *sp); +static void clear_lro_session(lro_t *lro); static void queue_rx_frame(struct sk_buff *skb); -static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro); -static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, - struct sk_buff *skb, u32 tcp_len); +static void update_L3L4_header(nic_t *sp, lro_t *lro); +static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len); #define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size #define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size diff --git a/trunk/drivers/net/sc92031.c b/trunk/drivers/net/sc92031.c deleted file mode 100644 index 7f800feaa9a2..000000000000 --- a/trunk/drivers/net/sc92031.c +++ /dev/null @@ -1,1620 +0,0 @@ -/* Silan SC92031 PCI Fast Ethernet Adapter driver - * - * Based on vendor drivers: - * Silan Fast Ethernet Netcard Driver: - * MODULE_AUTHOR ("gaoyonghong"); - * MODULE_DESCRIPTION ("SILAN Fast Ethernet driver"); - * MODULE_LICENSE("GPL"); - * 8139D Fast Ethernet driver: - * (C) 2002 by gaoyonghong - * MODULE_AUTHOR ("gaoyonghong"); - * MODULE_DESCRIPTION ("Rsltek 8139D PCI Fast Ethernet Adapter driver"); - * MODULE_LICENSE("GPL"); - * Both are almost identical and seem to be based on pci-skeleton.c - * - * Rewritten for 2.6 by Cesar Eduardo Barros - */ - -/* Note about set_mac_address: I don't know how to change the hardware - * matching, so you need to enable IFF_PROMISC when using it. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define PCI_VENDOR_ID_SILAN 0x1904 -#define PCI_DEVICE_ID_SILAN_SC92031 0x2031 -#define PCI_DEVICE_ID_SILAN_8139D 0x8139 - -#define SC92031_NAME "sc92031" -#define SC92031_DESCRIPTION "Silan SC92031 PCI Fast Ethernet Adapter driver" -#define SC92031_VERSION "2.0c" - -/* BAR 0 is MMIO, BAR 1 is PIO */ -#ifndef SC92031_USE_BAR -#define SC92031_USE_BAR 0 -#endif - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). */ -static int multicast_filter_limit = 64; -module_param(multicast_filter_limit, int, 0); -MODULE_PARM_DESC(multicast_filter_limit, - "Maximum number of filtered multicast addresses"); - -static int media; -module_param(media, int, 0); -MODULE_PARM_DESC(media, "Media type (0x00 = autodetect," - " 0x01 = 10M half, 0x02 = 10M full," - " 0x04 = 100M half, 0x08 = 100M full)"); - -/* Size of the in-memory receive ring. */ -#define RX_BUF_LEN_IDX 3 /* 0==8K, 1==16K, 2==32K, 3==64K ,4==128K*/ -#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) - -/* Number of Tx descriptor registers. */ -#define NUM_TX_DESC 4 - -/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/ -#define MAX_ETH_FRAME_SIZE 1536 - -/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */ -#define TX_BUF_SIZE MAX_ETH_FRAME_SIZE -#define TX_BUF_TOT_LEN (TX_BUF_SIZE * NUM_TX_DESC) - -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ -#define RX_FIFO_THRESH 7 /* Rx buffer level before first PCI xfer. */ - -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (4*HZ) - -#define SILAN_STATS_NUM 2 /* number of ETHTOOL_GSTATS */ - -/* media options */ -#define AUTOSELECT 0x00 -#define M10_HALF 0x01 -#define M10_FULL 0x02 -#define M100_HALF 0x04 -#define M100_FULL 0x08 - - /* Symbolic offsets to registers. */ -enum silan_registers { - Config0 = 0x00, // Config0 - Config1 = 0x04, // Config1 - RxBufWPtr = 0x08, // Rx buffer writer poiter - IntrStatus = 0x0C, // Interrupt status - IntrMask = 0x10, // Interrupt mask - RxbufAddr = 0x14, // Rx buffer start address - RxBufRPtr = 0x18, // Rx buffer read pointer - Txstatusall = 0x1C, // Transmit status of all descriptors - TxStatus0 = 0x20, // Transmit status (Four 32bit registers). - TxAddr0 = 0x30, // Tx descriptors (also four 32bit). - RxConfig = 0x40, // Rx configuration - MAC0 = 0x44, // Ethernet hardware address. - MAR0 = 0x4C, // Multicast filter. - RxStatus0 = 0x54, // Rx status - TxConfig = 0x5C, // Tx configuration - PhyCtrl = 0x60, // physical control - FlowCtrlConfig = 0x64, // flow control - Miicmd0 = 0x68, // Mii command0 register - Miicmd1 = 0x6C, // Mii command1 register - Miistatus = 0x70, // Mii status register - Timercnt = 0x74, // Timer counter register - TimerIntr = 0x78, // Timer interrupt register - PMConfig = 0x7C, // Power Manager configuration - CRC0 = 0x80, // Power Manager CRC ( Two 32bit regisers) - Wakeup0 = 0x88, // power Manager wakeup( Eight 64bit regiser) - LSBCRC0 = 0xC8, // power Manager LSBCRC(Two 32bit regiser) - TestD0 = 0xD0, - TestD4 = 0xD4, - TestD8 = 0xD8, -}; - -#define MII_BMCR 0 // Basic mode control register -#define MII_BMSR 1 // Basic mode status register -#define MII_JAB 16 -#define MII_OutputStatus 24 - -#define BMCR_FULLDPLX 0x0100 // Full duplex -#define BMCR_ANRESTART 0x0200 // Auto negotiation restart -#define BMCR_ANENABLE 0x1000 // Enable auto negotiation -#define BMCR_SPEED100 0x2000 // Select 100Mbps -#define BMSR_LSTATUS 0x0004 // Link status -#define PHY_16_JAB_ENB 0x1000 -#define PHY_16_PORT_ENB 0x1 - -enum IntrStatusBits { - LinkFail = 0x80000000, - LinkOK = 0x40000000, - TimeOut = 0x20000000, - RxOverflow = 0x0040, - RxOK = 0x0020, - TxOK = 0x0001, - IntrBits = LinkFail|LinkOK|TimeOut|RxOverflow|RxOK|TxOK, -}; - -enum TxStatusBits { - TxCarrierLost = 0x20000000, - TxAborted = 0x10000000, - TxOutOfWindow = 0x08000000, - TxNccShift = 22, - EarlyTxThresShift = 16, - TxStatOK = 0x8000, - TxUnderrun = 0x4000, - TxOwn = 0x2000, -}; - -enum RxStatusBits { - RxStatesOK = 0x80000, - RxBadAlign = 0x40000, - RxHugeFrame = 0x20000, - RxSmallFrame = 0x10000, - RxCRCOK = 0x8000, - RxCrlFrame = 0x4000, - Rx_Broadcast = 0x2000, - Rx_Multicast = 0x1000, - RxAddrMatch = 0x0800, - MiiErr = 0x0400, -}; - -enum RxConfigBits { - RxFullDx = 0x80000000, - RxEnb = 0x40000000, - RxSmall = 0x20000000, - RxHuge = 0x10000000, - RxErr = 0x08000000, - RxAllphys = 0x04000000, - RxMulticast = 0x02000000, - RxBroadcast = 0x01000000, - RxLoopBack = (1 << 23) | (1 << 22), - LowThresholdShift = 12, - HighThresholdShift = 2, -}; - -enum TxConfigBits { - TxFullDx = 0x80000000, - TxEnb = 0x40000000, - TxEnbPad = 0x20000000, - TxEnbHuge = 0x10000000, - TxEnbFCS = 0x08000000, - TxNoBackOff = 0x04000000, - TxEnbPrem = 0x02000000, - TxCareLostCrs = 0x1000000, - TxExdCollNum = 0xf00000, - TxDataRate = 0x80000, -}; - -enum PhyCtrlconfigbits { - PhyCtrlAne = 0x80000000, - PhyCtrlSpd100 = 0x40000000, - PhyCtrlSpd10 = 0x20000000, - PhyCtrlPhyBaseAddr = 0x1f000000, - PhyCtrlDux = 0x800000, - PhyCtrlReset = 0x400000, -}; - -enum FlowCtrlConfigBits { - FlowCtrlFullDX = 0x80000000, - FlowCtrlEnb = 0x40000000, -}; - -enum Config0Bits { - Cfg0_Reset = 0x80000000, - Cfg0_Anaoff = 0x40000000, - Cfg0_LDPS = 0x20000000, -}; - -enum Config1Bits { - Cfg1_EarlyRx = 1 << 31, - Cfg1_EarlyTx = 1 << 30, - - //rx buffer size - Cfg1_Rcv8K = 0x0, - Cfg1_Rcv16K = 0x1, - Cfg1_Rcv32K = 0x3, - Cfg1_Rcv64K = 0x7, - Cfg1_Rcv128K = 0xf, -}; - -enum MiiCmd0Bits { - Mii_Divider = 0x20000000, - Mii_WRITE = 0x400000, - Mii_READ = 0x200000, - Mii_SCAN = 0x100000, - Mii_Tamod = 0x80000, - Mii_Drvmod = 0x40000, - Mii_mdc = 0x20000, - Mii_mdoen = 0x10000, - Mii_mdo = 0x8000, - Mii_mdi = 0x4000, -}; - -enum MiiStatusBits { - Mii_StatusBusy = 0x80000000, -}; - -enum PMConfigBits { - PM_Enable = 1 << 31, - PM_LongWF = 1 << 30, - PM_Magic = 1 << 29, - PM_LANWake = 1 << 28, - PM_LWPTN = (1 << 27 | 1<< 26), - PM_LinkUp = 1 << 25, - PM_WakeUp = 1 << 24, -}; - -/* Locking rules: - * priv->lock protects most of the fields of priv and most of the - * hardware registers. It does not have to protect against softirqs - * between sc92031_disable_interrupts and sc92031_enable_interrupts; - * it also does not need to be used in ->open and ->stop while the - * device interrupts are off. - * Not having to protect against softirqs is very useful due to heavy - * use of mdelay() at _sc92031_reset. - * Functions prefixed with _sc92031_ must be called with the lock held; - * functions prefixed with sc92031_ must be called without the lock held. - * Use mmiowb() before unlocking if the hardware was written to. - */ - -/* Locking rules for the interrupt: - * - the interrupt and the tasklet never run at the same time - * - neither run between sc92031_disable_interrupts and - * sc92031_enable_interrupt - */ - -struct sc92031_priv { - spinlock_t lock; - /* iomap.h cookie */ - void __iomem *port_base; - /* pci device structure */ - struct pci_dev *pdev; - /* tasklet */ - struct tasklet_struct tasklet; - - /* CPU address of rx ring */ - void *rx_ring; - /* PCI address of rx ring */ - dma_addr_t rx_ring_dma_addr; - /* PCI address of rx ring read pointer */ - dma_addr_t rx_ring_tail; - - /* tx ring write index */ - unsigned tx_head; - /* tx ring read index */ - unsigned tx_tail; - /* CPU address of tx bounce buffer */ - void *tx_bufs; - /* PCI address of tx bounce buffer */ - dma_addr_t tx_bufs_dma_addr; - - /* copies of some hardware registers */ - u32 intr_status; - atomic_t intr_mask; - u32 rx_config; - u32 tx_config; - u32 pm_config; - - /* copy of some flags from dev->flags */ - unsigned int mc_flags; - - /* for ETHTOOL_GSTATS */ - u64 tx_timeouts; - u64 rx_loss; - - /* for dev->get_stats */ - long rx_value; - struct net_device_stats stats; -}; - -/* I don't know which registers can be safely read; however, I can guess - * MAC0 is one of them. */ -static inline void _sc92031_dummy_read(void __iomem *port_base) -{ - ioread32(port_base + MAC0); -} - -static u32 _sc92031_mii_wait(void __iomem *port_base) -{ - u32 mii_status; - - do { - udelay(10); - mii_status = ioread32(port_base + Miistatus); - } while (mii_status & Mii_StatusBusy); - - return mii_status; -} - -static u32 _sc92031_mii_cmd(void __iomem *port_base, u32 cmd0, u32 cmd1) -{ - iowrite32(Mii_Divider, port_base + Miicmd0); - - _sc92031_mii_wait(port_base); - - iowrite32(cmd1, port_base + Miicmd1); - iowrite32(Mii_Divider | cmd0, port_base + Miicmd0); - - return _sc92031_mii_wait(port_base); -} - -static void _sc92031_mii_scan(void __iomem *port_base) -{ - _sc92031_mii_cmd(port_base, Mii_SCAN, 0x1 << 6); -} - -static u16 _sc92031_mii_read(void __iomem *port_base, unsigned reg) -{ - return _sc92031_mii_cmd(port_base, Mii_READ, reg << 6) >> 13; -} - -static void _sc92031_mii_write(void __iomem *port_base, unsigned reg, u16 val) -{ - _sc92031_mii_cmd(port_base, Mii_WRITE, (reg << 6) | ((u32)val << 11)); -} - -static void sc92031_disable_interrupts(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - - /* tell the tasklet/interrupt not to enable interrupts */ - atomic_set(&priv->intr_mask, 0); - wmb(); - - /* stop interrupts */ - iowrite32(0, port_base + IntrMask); - _sc92031_dummy_read(port_base); - mmiowb(); - - /* wait for any concurrent interrupt/tasklet to finish */ - synchronize_irq(dev->irq); - tasklet_disable(&priv->tasklet); -} - -static void sc92031_enable_interrupts(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - - tasklet_enable(&priv->tasklet); - - atomic_set(&priv->intr_mask, IntrBits); - wmb(); - - iowrite32(IntrBits, port_base + IntrMask); - mmiowb(); -} - -static void _sc92031_disable_tx_rx(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - - priv->rx_config &= ~RxEnb; - priv->tx_config &= ~TxEnb; - iowrite32(priv->rx_config, port_base + RxConfig); - iowrite32(priv->tx_config, port_base + TxConfig); -} - -static void _sc92031_enable_tx_rx(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - - priv->rx_config |= RxEnb; - priv->tx_config |= TxEnb; - iowrite32(priv->rx_config, port_base + RxConfig); - iowrite32(priv->tx_config, port_base + TxConfig); -} - -static void _sc92031_tx_clear(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - - while (priv->tx_head - priv->tx_tail > 0) { - priv->tx_tail++; - priv->stats.tx_dropped++; - } - priv->tx_head = priv->tx_tail = 0; -} - -static void _sc92031_set_mar(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u32 mar0 = 0, mar1 = 0; - - if ((dev->flags & IFF_PROMISC) - || dev->mc_count > multicast_filter_limit - || (dev->flags & IFF_ALLMULTI)) - mar0 = mar1 = 0xffffffff; - else if (dev->flags & IFF_MULTICAST) { - struct dev_mc_list *mc_list; - - for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) { - u32 crc; - unsigned bit = 0; - - crc = ~ether_crc(ETH_ALEN, mc_list->dmi_addr); - crc >>= 24; - - if (crc & 0x01) bit |= 0x02; - if (crc & 0x02) bit |= 0x01; - if (crc & 0x10) bit |= 0x20; - if (crc & 0x20) bit |= 0x10; - if (crc & 0x40) bit |= 0x08; - if (crc & 0x80) bit |= 0x04; - - if (bit > 31) - mar0 |= 0x1 << (bit - 32); - else - mar1 |= 0x1 << bit; - } - } - - iowrite32(mar0, port_base + MAR0); - iowrite32(mar1, port_base + MAR0 + 4); -} - -static void _sc92031_set_rx_config(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - unsigned int old_mc_flags; - u32 rx_config_bits = 0; - - old_mc_flags = priv->mc_flags; - - if (dev->flags & IFF_PROMISC) - rx_config_bits |= RxSmall | RxHuge | RxErr | RxBroadcast - | RxMulticast | RxAllphys; - - if (dev->flags & (IFF_ALLMULTI | IFF_MULTICAST)) - rx_config_bits |= RxMulticast; - - if (dev->flags & IFF_BROADCAST) - rx_config_bits |= RxBroadcast; - - priv->rx_config &= ~(RxSmall | RxHuge | RxErr | RxBroadcast - | RxMulticast | RxAllphys); - priv->rx_config |= rx_config_bits; - - priv->mc_flags = dev->flags & (IFF_PROMISC | IFF_ALLMULTI - | IFF_MULTICAST | IFF_BROADCAST); - - if (netif_carrier_ok(dev) && priv->mc_flags != old_mc_flags) - iowrite32(priv->rx_config, port_base + RxConfig); -} - -static bool _sc92031_check_media(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u16 bmsr; - - bmsr = _sc92031_mii_read(port_base, MII_BMSR); - rmb(); - if (bmsr & BMSR_LSTATUS) { - bool speed_100, duplex_full; - u32 flow_ctrl_config = 0; - u16 output_status = _sc92031_mii_read(port_base, - MII_OutputStatus); - _sc92031_mii_scan(port_base); - - speed_100 = output_status & 0x2; - duplex_full = output_status & 0x4; - - /* Initial Tx/Rx configuration */ - priv->rx_config = (0x40 << LowThresholdShift) | (0x1c0 << HighThresholdShift); - priv->tx_config = 0x48800000; - - /* NOTE: vendor driver had dead code here to enable tx padding */ - - if (!speed_100) - priv->tx_config |= 0x80000; - - // configure rx mode - _sc92031_set_rx_config(dev); - - if (duplex_full) { - priv->rx_config |= RxFullDx; - priv->tx_config |= TxFullDx; - flow_ctrl_config = FlowCtrlFullDX | FlowCtrlEnb; - } else { - priv->rx_config &= ~RxFullDx; - priv->tx_config &= ~TxFullDx; - } - - _sc92031_set_mar(dev); - _sc92031_set_rx_config(dev); - _sc92031_enable_tx_rx(dev); - iowrite32(flow_ctrl_config, port_base + FlowCtrlConfig); - - netif_carrier_on(dev); - - if (printk_ratelimit()) - printk(KERN_INFO "%s: link up, %sMbps, %s-duplex\n", - dev->name, - speed_100 ? "100" : "10", - duplex_full ? "full" : "half"); - return true; - } else { - _sc92031_mii_scan(port_base); - - netif_carrier_off(dev); - - _sc92031_disable_tx_rx(dev); - - if (printk_ratelimit()) - printk(KERN_INFO "%s: link down\n", dev->name); - return false; - } -} - -static void _sc92031_phy_reset(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u32 phy_ctrl; - - phy_ctrl = ioread32(port_base + PhyCtrl); - phy_ctrl &= ~(PhyCtrlDux | PhyCtrlSpd100 | PhyCtrlSpd10); - phy_ctrl |= PhyCtrlAne | PhyCtrlReset; - - switch (media) { - default: - case AUTOSELECT: - phy_ctrl |= PhyCtrlDux | PhyCtrlSpd100 | PhyCtrlSpd10; - break; - case M10_HALF: - phy_ctrl |= PhyCtrlSpd10; - break; - case M10_FULL: - phy_ctrl |= PhyCtrlDux | PhyCtrlSpd10; - break; - case M100_HALF: - phy_ctrl |= PhyCtrlSpd100; - break; - case M100_FULL: - phy_ctrl |= PhyCtrlDux | PhyCtrlSpd100; - break; - } - - iowrite32(phy_ctrl, port_base + PhyCtrl); - mdelay(10); - - phy_ctrl &= ~PhyCtrlReset; - iowrite32(phy_ctrl, port_base + PhyCtrl); - mdelay(1); - - _sc92031_mii_write(port_base, MII_JAB, - PHY_16_JAB_ENB | PHY_16_PORT_ENB); - _sc92031_mii_scan(port_base); - - netif_carrier_off(dev); - netif_stop_queue(dev); -} - -static void _sc92031_reset(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - - /* disable PM */ - iowrite32(0, port_base + PMConfig); - - /* soft reset the chip */ - iowrite32(Cfg0_Reset, port_base + Config0); - mdelay(200); - - iowrite32(0, port_base + Config0); - mdelay(10); - - /* disable interrupts */ - iowrite32(0, port_base + IntrMask); - - /* clear multicast address */ - iowrite32(0, port_base + MAR0); - iowrite32(0, port_base + MAR0 + 4); - - /* init rx ring */ - iowrite32(priv->rx_ring_dma_addr, port_base + RxbufAddr); - priv->rx_ring_tail = priv->rx_ring_dma_addr; - - /* init tx ring */ - _sc92031_tx_clear(dev); - - /* clear old register values */ - priv->intr_status = 0; - atomic_set(&priv->intr_mask, 0); - priv->rx_config = 0; - priv->tx_config = 0; - priv->mc_flags = 0; - - /* configure rx buffer size */ - /* NOTE: vendor driver had dead code here to enable early tx/rx */ - iowrite32(Cfg1_Rcv64K, port_base + Config1); - - _sc92031_phy_reset(dev); - _sc92031_check_media(dev); - - /* calculate rx fifo overflow */ - priv->rx_value = 0; - - /* enable PM */ - iowrite32(priv->pm_config, port_base + PMConfig); - - /* clear intr register */ - ioread32(port_base + IntrStatus); -} - -static void _sc92031_tx_tasklet(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - - unsigned old_tx_tail; - unsigned entry; - u32 tx_status; - - old_tx_tail = priv->tx_tail; - while (priv->tx_head - priv->tx_tail > 0) { - entry = priv->tx_tail % NUM_TX_DESC; - tx_status = ioread32(port_base + TxStatus0 + entry * 4); - - if (!(tx_status & (TxStatOK | TxUnderrun | TxAborted))) - break; - - priv->tx_tail++; - - if (tx_status & TxStatOK) { - priv->stats.tx_bytes += tx_status & 0x1fff; - priv->stats.tx_packets++; - /* Note: TxCarrierLost is always asserted at 100mbps. */ - priv->stats.collisions += (tx_status >> 22) & 0xf; - } - - if (tx_status & (TxOutOfWindow | TxAborted)) { - priv->stats.tx_errors++; - - if (tx_status & TxAborted) - priv->stats.tx_aborted_errors++; - - if (tx_status & TxCarrierLost) - priv->stats.tx_carrier_errors++; - - if (tx_status & TxOutOfWindow) - priv->stats.tx_window_errors++; - } - - if (tx_status & TxUnderrun) - priv->stats.tx_fifo_errors++; - } - - if (priv->tx_tail != old_tx_tail) - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); -} - -static void _sc92031_rx_tasklet_error(u32 rx_status, - struct sc92031_priv *priv, unsigned rx_size) -{ - if(rx_size > (MAX_ETH_FRAME_SIZE + 4) || rx_size < 16) { - priv->stats.rx_errors++; - priv->stats.rx_length_errors++; - } - - if (!(rx_status & RxStatesOK)) { - priv->stats.rx_errors++; - - if (rx_status & (RxHugeFrame | RxSmallFrame)) - priv->stats.rx_length_errors++; - - if (rx_status & RxBadAlign) - priv->stats.rx_frame_errors++; - - if (!(rx_status & RxCRCOK)) - priv->stats.rx_crc_errors++; - } else - priv->rx_loss++; -} - -static void _sc92031_rx_tasklet(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - - dma_addr_t rx_ring_head; - unsigned rx_len; - unsigned rx_ring_offset; - void *rx_ring = priv->rx_ring; - - rx_ring_head = ioread32(port_base + RxBufWPtr); - rmb(); - - /* rx_ring_head is only 17 bits in the RxBufWPtr register. - * we need to change it to 32 bits physical address - */ - rx_ring_head &= (dma_addr_t)(RX_BUF_LEN - 1); - rx_ring_head |= priv->rx_ring_dma_addr & ~(dma_addr_t)(RX_BUF_LEN - 1); - if (rx_ring_head < priv->rx_ring_dma_addr) - rx_ring_head += RX_BUF_LEN; - - if (rx_ring_head >= priv->rx_ring_tail) - rx_len = rx_ring_head - priv->rx_ring_tail; - else - rx_len = RX_BUF_LEN - (priv->rx_ring_tail - rx_ring_head); - - if (!rx_len) - return; - - if (unlikely(rx_len > RX_BUF_LEN)) { - if (printk_ratelimit()) - printk(KERN_ERR "%s: rx packets length > rx buffer\n", - dev->name); - return; - } - - rx_ring_offset = (priv->rx_ring_tail - priv->rx_ring_dma_addr) % RX_BUF_LEN; - - while (rx_len) { - u32 rx_status; - unsigned rx_size, rx_size_align, pkt_size; - struct sk_buff *skb; - - rx_status = le32_to_cpup((__le32 *)(rx_ring + rx_ring_offset)); - rmb(); - - rx_size = rx_status >> 20; - rx_size_align = (rx_size + 3) & ~3; // for 4 bytes aligned - pkt_size = rx_size - 4; // Omit the four octet CRC from the length. - - rx_ring_offset = (rx_ring_offset + 4) % RX_BUF_LEN; - - if (unlikely(rx_status == 0 - || rx_size > (MAX_ETH_FRAME_SIZE + 4) - || rx_size < 16 - || !(rx_status & RxStatesOK))) { - _sc92031_rx_tasklet_error(rx_status, priv, rx_size); - break; - } - - if (unlikely(rx_size_align + 4 > rx_len)) { - if (printk_ratelimit()) - printk(KERN_ERR "%s: rx_len is too small\n", dev->name); - break; - } - - rx_len -= rx_size_align + 4; - - skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN); - if (unlikely(!skb)) { - if (printk_ratelimit()) - printk(KERN_ERR "%s: Couldn't allocate a skb_buff for a packet of size %u\n", - dev->name, pkt_size); - goto next; - } - - skb_reserve(skb, NET_IP_ALIGN); - - if ((rx_ring_offset + pkt_size) > RX_BUF_LEN) { - memcpy(skb_put(skb, RX_BUF_LEN - rx_ring_offset), - rx_ring + rx_ring_offset, RX_BUF_LEN - rx_ring_offset); - memcpy(skb_put(skb, pkt_size - (RX_BUF_LEN - rx_ring_offset)), - rx_ring, pkt_size - (RX_BUF_LEN - rx_ring_offset)); - } else { - memcpy(skb_put(skb, pkt_size), rx_ring + rx_ring_offset, pkt_size); - } - - skb->dev = dev; - skb->protocol = eth_type_trans(skb, dev); - dev->last_rx = jiffies; - netif_rx(skb); - - priv->stats.rx_bytes += pkt_size; - priv->stats.rx_packets++; - - if (rx_status & Rx_Multicast) - priv->stats.multicast++; - - next: - rx_ring_offset = (rx_ring_offset + rx_size_align) % RX_BUF_LEN; - } - mb(); - - priv->rx_ring_tail = rx_ring_head; - iowrite32(priv->rx_ring_tail, port_base + RxBufRPtr); -} - -static void _sc92031_link_tasklet(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - - if (_sc92031_check_media(dev)) - netif_wake_queue(dev); - else { - netif_stop_queue(dev); - priv->stats.tx_carrier_errors++; - } -} - -static void sc92031_tasklet(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u32 intr_status, intr_mask; - - intr_status = priv->intr_status; - - spin_lock(&priv->lock); - - if (unlikely(!netif_running(dev))) - goto out; - - if (intr_status & TxOK) - _sc92031_tx_tasklet(dev); - - if (intr_status & RxOK) - _sc92031_rx_tasklet(dev); - - if (intr_status & RxOverflow) - priv->stats.rx_errors++; - - if (intr_status & TimeOut) { - priv->stats.rx_errors++; - priv->stats.rx_length_errors++; - } - - if (intr_status & (LinkFail | LinkOK)) - _sc92031_link_tasklet(dev); - -out: - intr_mask = atomic_read(&priv->intr_mask); - rmb(); - - iowrite32(intr_mask, port_base + IntrMask); - mmiowb(); - - spin_unlock(&priv->lock); -} - -static irqreturn_t sc92031_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u32 intr_status, intr_mask; - - /* mask interrupts before clearing IntrStatus */ - iowrite32(0, port_base + IntrMask); - _sc92031_dummy_read(port_base); - - intr_status = ioread32(port_base + IntrStatus); - if (unlikely(intr_status == 0xffffffff)) - return IRQ_NONE; // hardware has gone missing - - intr_status &= IntrBits; - if (!intr_status) - goto out_none; - - priv->intr_status = intr_status; - tasklet_schedule(&priv->tasklet); - - return IRQ_HANDLED; - -out_none: - intr_mask = atomic_read(&priv->intr_mask); - rmb(); - - iowrite32(intr_mask, port_base + IntrMask); - mmiowb(); - - return IRQ_NONE; -} - -static struct net_device_stats *sc92031_get_stats(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - - // FIXME I do not understand what is this trying to do. - if (netif_running(dev)) { - int temp; - - spin_lock_bh(&priv->lock); - - /* Update the error count. */ - temp = (ioread32(port_base + RxStatus0) >> 16) & 0xffff; - - if (temp == 0xffff) { - priv->rx_value += temp; - priv->stats.rx_fifo_errors = priv->rx_value; - } else { - priv->stats.rx_fifo_errors = temp + priv->rx_value; - } - - spin_unlock_bh(&priv->lock); - } - - return &priv->stats; -} - -static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - int err = 0; - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - - unsigned len; - unsigned entry; - u32 tx_status; - - if (unlikely(skb->len > TX_BUF_SIZE)) { - err = -EMSGSIZE; - priv->stats.tx_dropped++; - goto out; - } - - spin_lock_bh(&priv->lock); - - if (unlikely(!netif_carrier_ok(dev))) { - err = -ENOLINK; - priv->stats.tx_dropped++; - goto out_unlock; - } - - BUG_ON(priv->tx_head - priv->tx_tail >= NUM_TX_DESC); - - entry = priv->tx_head++ % NUM_TX_DESC; - - skb_copy_and_csum_dev(skb, priv->tx_bufs + entry * TX_BUF_SIZE); - - len = skb->len; - if (unlikely(len < ETH_ZLEN)) { - memset(priv->tx_bufs + entry * TX_BUF_SIZE + len, - 0, ETH_ZLEN - len); - len = ETH_ZLEN; - } - - wmb(); - - if (len < 100) - tx_status = len; - else if (len < 300) - tx_status = 0x30000 | len; - else - tx_status = 0x50000 | len; - - iowrite32(priv->tx_bufs_dma_addr + entry * TX_BUF_SIZE, - port_base + TxAddr0 + entry * 4); - iowrite32(tx_status, port_base + TxStatus0 + entry * 4); - mmiowb(); - - dev->trans_start = jiffies; - - if (priv->tx_head - priv->tx_tail >= NUM_TX_DESC) - netif_stop_queue(dev); - -out_unlock: - spin_unlock_bh(&priv->lock); - -out: - dev_kfree_skb(skb); - - return err; -} - -static int sc92031_open(struct net_device *dev) -{ - int err; - struct sc92031_priv *priv = netdev_priv(dev); - struct pci_dev *pdev = priv->pdev; - - priv->rx_ring = pci_alloc_consistent(pdev, RX_BUF_LEN, - &priv->rx_ring_dma_addr); - if (unlikely(!priv->rx_ring)) { - err = -ENOMEM; - goto out_alloc_rx_ring; - } - - priv->tx_bufs = pci_alloc_consistent(pdev, TX_BUF_TOT_LEN, - &priv->tx_bufs_dma_addr); - if (unlikely(!priv->tx_bufs)) { - err = -ENOMEM; - goto out_alloc_tx_bufs; - } - priv->tx_head = priv->tx_tail = 0; - - err = request_irq(pdev->irq, sc92031_interrupt, - SA_SHIRQ, dev->name, dev); - if (unlikely(err < 0)) - goto out_request_irq; - - priv->pm_config = 0; - - /* Interrupts already disabled by sc92031_stop or sc92031_probe */ - spin_lock(&priv->lock); - - _sc92031_reset(dev); - mmiowb(); - - spin_unlock(&priv->lock); - sc92031_enable_interrupts(dev); - - if (netif_carrier_ok(dev)) - netif_start_queue(dev); - else - netif_tx_disable(dev); - - return 0; - -out_request_irq: - pci_free_consistent(pdev, TX_BUF_TOT_LEN, priv->tx_bufs, - priv->tx_bufs_dma_addr); -out_alloc_tx_bufs: - pci_free_consistent(pdev, RX_BUF_LEN, priv->rx_ring, - priv->rx_ring_dma_addr); -out_alloc_rx_ring: - return err; -} - -static int sc92031_stop(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - struct pci_dev *pdev = priv->pdev; - - netif_tx_disable(dev); - - /* Disable interrupts, stop Tx and Rx. */ - sc92031_disable_interrupts(dev); - - spin_lock(&priv->lock); - - _sc92031_disable_tx_rx(dev); - _sc92031_tx_clear(dev); - mmiowb(); - - spin_unlock(&priv->lock); - - free_irq(pdev->irq, dev); - pci_free_consistent(pdev, TX_BUF_TOT_LEN, priv->tx_bufs, - priv->tx_bufs_dma_addr); - pci_free_consistent(pdev, RX_BUF_LEN, priv->rx_ring, - priv->rx_ring_dma_addr); - - return 0; -} - -static void sc92031_set_multicast_list(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - - spin_lock_bh(&priv->lock); - - _sc92031_set_mar(dev); - _sc92031_set_rx_config(dev); - mmiowb(); - - spin_unlock_bh(&priv->lock); -} - -static void sc92031_tx_timeout(struct net_device *dev) -{ - struct sc92031_priv *priv = netdev_priv(dev); - - /* Disable interrupts by clearing the interrupt mask.*/ - sc92031_disable_interrupts(dev); - - spin_lock(&priv->lock); - - priv->tx_timeouts++; - - _sc92031_reset(dev); - mmiowb(); - - spin_unlock(&priv->lock); - - /* enable interrupts */ - sc92031_enable_interrupts(dev); - - if (netif_carrier_ok(dev)) - netif_wake_queue(dev); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void sc92031_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - if (sc92031_interrupt(dev->irq, dev) != IRQ_NONE) - sc92031_tasklet((unsigned long)dev); - enable_irq(dev->irq); -} -#endif - -static int sc92031_ethtool_get_settings(struct net_device *dev, - struct ethtool_cmd *cmd) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u8 phy_address; - u32 phy_ctrl; - u16 output_status; - - spin_lock_bh(&priv->lock); - - phy_address = ioread32(port_base + Miicmd1) >> 27; - phy_ctrl = ioread32(port_base + PhyCtrl); - - output_status = _sc92031_mii_read(port_base, MII_OutputStatus); - _sc92031_mii_scan(port_base); - mmiowb(); - - spin_unlock_bh(&priv->lock); - - cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full - | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full - | SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII; - - cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; - - if ((phy_ctrl & (PhyCtrlDux | PhyCtrlSpd100 | PhyCtrlSpd10)) - == (PhyCtrlDux | PhyCtrlSpd100 | PhyCtrlSpd10)) - cmd->advertising |= ADVERTISED_Autoneg; - - if ((phy_ctrl & PhyCtrlSpd10) == PhyCtrlSpd10) - cmd->advertising |= ADVERTISED_10baseT_Half; - - if ((phy_ctrl & (PhyCtrlSpd10 | PhyCtrlDux)) - == (PhyCtrlSpd10 | PhyCtrlDux)) - cmd->advertising |= ADVERTISED_10baseT_Full; - - if ((phy_ctrl & PhyCtrlSpd100) == PhyCtrlSpd100) - cmd->advertising |= ADVERTISED_100baseT_Half; - - if ((phy_ctrl & (PhyCtrlSpd100 | PhyCtrlDux)) - == (PhyCtrlSpd100 | PhyCtrlDux)) - cmd->advertising |= ADVERTISED_100baseT_Full; - - if (phy_ctrl & PhyCtrlAne) - cmd->advertising |= ADVERTISED_Autoneg; - - cmd->speed = (output_status & 0x2) ? SPEED_100 : SPEED_10; - cmd->duplex = (output_status & 0x4) ? DUPLEX_FULL : DUPLEX_HALF; - cmd->port = PORT_MII; - cmd->phy_address = phy_address; - cmd->transceiver = XCVR_INTERNAL; - cmd->autoneg = (phy_ctrl & PhyCtrlAne) ? AUTONEG_ENABLE : AUTONEG_DISABLE; - - return 0; -} - -static int sc92031_ethtool_set_settings(struct net_device *dev, - struct ethtool_cmd *cmd) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u32 phy_ctrl; - u32 old_phy_ctrl; - - if (!(cmd->speed == SPEED_10 || cmd->speed == SPEED_100)) - return -EINVAL; - if (!(cmd->duplex == DUPLEX_HALF || cmd->duplex == DUPLEX_FULL)) - return -EINVAL; - if (!(cmd->port == PORT_MII)) - return -EINVAL; - if (!(cmd->phy_address == 0x1f)) - return -EINVAL; - if (!(cmd->transceiver == XCVR_INTERNAL)) - return -EINVAL; - if (!(cmd->autoneg == AUTONEG_DISABLE || cmd->autoneg == AUTONEG_ENABLE)) - return -EINVAL; - - if (cmd->autoneg == AUTONEG_ENABLE) { - if (!(cmd->advertising & (ADVERTISED_Autoneg - | ADVERTISED_100baseT_Full - | ADVERTISED_100baseT_Half - | ADVERTISED_10baseT_Full - | ADVERTISED_10baseT_Half))) - return -EINVAL; - - phy_ctrl = PhyCtrlAne; - - // FIXME: I'm not sure what the original code was trying to do - if (cmd->advertising & ADVERTISED_Autoneg) - phy_ctrl |= PhyCtrlDux | PhyCtrlSpd100 | PhyCtrlSpd10; - if (cmd->advertising & ADVERTISED_100baseT_Full) - phy_ctrl |= PhyCtrlDux | PhyCtrlSpd100; - if (cmd->advertising & ADVERTISED_100baseT_Half) - phy_ctrl |= PhyCtrlSpd100; - if (cmd->advertising & ADVERTISED_10baseT_Full) - phy_ctrl |= PhyCtrlSpd10 | PhyCtrlDux; - if (cmd->advertising & ADVERTISED_10baseT_Half) - phy_ctrl |= PhyCtrlSpd10; - } else { - // FIXME: Whole branch guessed - phy_ctrl = 0; - - if (cmd->speed == SPEED_10) - phy_ctrl |= PhyCtrlSpd10; - else /* cmd->speed == SPEED_100 */ - phy_ctrl |= PhyCtrlSpd100; - - if (cmd->duplex == DUPLEX_FULL) - phy_ctrl |= PhyCtrlDux; - } - - spin_lock_bh(&priv->lock); - - old_phy_ctrl = ioread32(port_base + PhyCtrl); - phy_ctrl |= old_phy_ctrl & ~(PhyCtrlAne | PhyCtrlDux - | PhyCtrlSpd100 | PhyCtrlSpd10); - if (phy_ctrl != old_phy_ctrl) - iowrite32(phy_ctrl, port_base + PhyCtrl); - - spin_unlock_bh(&priv->lock); - - return 0; -} - -static void sc92031_ethtool_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *drvinfo) -{ - struct sc92031_priv *priv = netdev_priv(dev); - struct pci_dev *pdev = priv->pdev; - - strcpy(drvinfo->driver, SC92031_NAME); - strcpy(drvinfo->version, SC92031_VERSION); - strcpy(drvinfo->bus_info, pci_name(pdev)); -} - -static void sc92031_ethtool_get_wol(struct net_device *dev, - struct ethtool_wolinfo *wolinfo) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u32 pm_config; - - spin_lock_bh(&priv->lock); - pm_config = ioread32(port_base + PMConfig); - spin_unlock_bh(&priv->lock); - - // FIXME: Guessed - wolinfo->supported = WAKE_PHY | WAKE_MAGIC - | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; - wolinfo->wolopts = 0; - - if (pm_config & PM_LinkUp) - wolinfo->wolopts |= WAKE_PHY; - - if (pm_config & PM_Magic) - wolinfo->wolopts |= WAKE_MAGIC; - - if (pm_config & PM_WakeUp) - // FIXME: Guessed - wolinfo->wolopts |= WAKE_UCAST | WAKE_MCAST | WAKE_BCAST; -} - -static int sc92031_ethtool_set_wol(struct net_device *dev, - struct ethtool_wolinfo *wolinfo) -{ - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u32 pm_config; - - spin_lock_bh(&priv->lock); - - pm_config = ioread32(port_base + PMConfig) - & ~(PM_LinkUp | PM_Magic | PM_WakeUp); - - if (wolinfo->wolopts & WAKE_PHY) - pm_config |= PM_LinkUp; - - if (wolinfo->wolopts & WAKE_MAGIC) - pm_config |= PM_Magic; - - // FIXME: Guessed - if (wolinfo->wolopts & (WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)) - pm_config |= PM_WakeUp; - - priv->pm_config = pm_config; - iowrite32(pm_config, port_base + PMConfig); - mmiowb(); - - spin_unlock_bh(&priv->lock); - - return 0; -} - -static int sc92031_ethtool_nway_reset(struct net_device *dev) -{ - int err = 0; - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem *port_base = priv->port_base; - u16 bmcr; - - spin_lock_bh(&priv->lock); - - bmcr = _sc92031_mii_read(port_base, MII_BMCR); - if (!(bmcr & BMCR_ANENABLE)) { - err = -EINVAL; - goto out; - } - - _sc92031_mii_write(port_base, MII_BMCR, bmcr | BMCR_ANRESTART); - -out: - _sc92031_mii_scan(port_base); - mmiowb(); - - spin_unlock_bh(&priv->lock); - - return err; -} - -static const char sc92031_ethtool_stats_strings[SILAN_STATS_NUM][ETH_GSTRING_LEN] = { - "tx_timeout", - "rx_loss", -}; - -static void sc92031_ethtool_get_strings(struct net_device *dev, - u32 stringset, u8 *data) -{ - if (stringset == ETH_SS_STATS) - memcpy(data, sc92031_ethtool_stats_strings, - SILAN_STATS_NUM * ETH_GSTRING_LEN); -} - -static int sc92031_ethtool_get_stats_count(struct net_device *dev) -{ - return SILAN_STATS_NUM; -} - -static void sc92031_ethtool_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct sc92031_priv *priv = netdev_priv(dev); - - spin_lock_bh(&priv->lock); - data[0] = priv->tx_timeouts; - data[1] = priv->rx_loss; - spin_unlock_bh(&priv->lock); -} - -static struct ethtool_ops sc92031_ethtool_ops = { - .get_settings = sc92031_ethtool_get_settings, - .set_settings = sc92031_ethtool_set_settings, - .get_drvinfo = sc92031_ethtool_get_drvinfo, - .get_wol = sc92031_ethtool_get_wol, - .set_wol = sc92031_ethtool_set_wol, - .nway_reset = sc92031_ethtool_nway_reset, - .get_link = ethtool_op_get_link, - .get_tx_csum = ethtool_op_get_tx_csum, - .get_sg = ethtool_op_get_sg, - .get_tso = ethtool_op_get_tso, - .get_strings = sc92031_ethtool_get_strings, - .get_stats_count = sc92031_ethtool_get_stats_count, - .get_ethtool_stats = sc92031_ethtool_get_ethtool_stats, - .get_perm_addr = ethtool_op_get_perm_addr, - .get_ufo = ethtool_op_get_ufo, -}; - -static int __devinit sc92031_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int err; - void __iomem* port_base; - struct net_device *dev; - struct sc92031_priv *priv; - u32 mac0, mac1; - - err = pci_enable_device(pdev); - if (unlikely(err < 0)) - goto out_enable_device; - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (unlikely(err < 0)) - goto out_set_dma_mask; - - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - if (unlikely(err < 0)) - goto out_set_dma_mask; - - err = pci_request_regions(pdev, SC92031_NAME); - if (unlikely(err < 0)) - goto out_request_regions; - - port_base = pci_iomap(pdev, SC92031_USE_BAR, 0); - if (unlikely(!port_base)) { - err = -EIO; - goto out_iomap; - } - - dev = alloc_etherdev(sizeof(struct sc92031_priv)); - if (unlikely(!dev)) { - err = -ENOMEM; - goto out_alloc_etherdev; - } - - pci_set_drvdata(pdev, dev); - -#if SC92031_USE_BAR == 0 - dev->mem_start = pci_resource_start(pdev, SC92031_USE_BAR); - dev->mem_end = pci_resource_end(pdev, SC92031_USE_BAR); -#elif SC92031_USE_BAR == 1 - dev->base_addr = pci_resource_start(pdev, SC92031_USE_BAR); -#endif - dev->irq = pdev->irq; - - /* faked with skb_copy_and_csum_dev */ - dev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA; - - dev->get_stats = sc92031_get_stats; - dev->ethtool_ops = &sc92031_ethtool_ops; - dev->hard_start_xmit = sc92031_start_xmit; - dev->watchdog_timeo = TX_TIMEOUT; - dev->open = sc92031_open; - dev->stop = sc92031_stop; - dev->set_multicast_list = sc92031_set_multicast_list; - dev->tx_timeout = sc92031_tx_timeout; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = sc92031_poll_controller; -#endif - - priv = netdev_priv(dev); - spin_lock_init(&priv->lock); - priv->port_base = port_base; - priv->pdev = pdev; - tasklet_init(&priv->tasklet, sc92031_tasklet, (unsigned long)dev); - /* Fudge tasklet count so the call to sc92031_enable_interrupts at - * sc92031_open will work correctly */ - tasklet_disable_nosync(&priv->tasklet); - - /* PCI PM Wakeup */ - iowrite32((~PM_LongWF & ~PM_LWPTN) | PM_Enable, port_base + PMConfig); - - mac0 = ioread32(port_base + MAC0); - mac1 = ioread32(port_base + MAC0 + 4); - dev->dev_addr[0] = dev->perm_addr[0] = mac0 >> 24; - dev->dev_addr[1] = dev->perm_addr[1] = mac0 >> 16; - dev->dev_addr[2] = dev->perm_addr[2] = mac0 >> 8; - dev->dev_addr[3] = dev->perm_addr[3] = mac0; - dev->dev_addr[4] = dev->perm_addr[4] = mac1 >> 8; - dev->dev_addr[5] = dev->perm_addr[5] = mac1; - - err = register_netdev(dev); - if (err < 0) - goto out_register_netdev; - - return 0; - -out_register_netdev: - free_netdev(dev); -out_alloc_etherdev: - pci_iounmap(pdev, port_base); -out_iomap: - pci_release_regions(pdev); -out_request_regions: -out_set_dma_mask: - pci_disable_device(pdev); -out_enable_device: - return err; -} - -static void __devexit sc92031_remove(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct sc92031_priv *priv = netdev_priv(dev); - void __iomem* port_base = priv->port_base; - - unregister_netdev(dev); - free_netdev(dev); - pci_iounmap(pdev, port_base); - pci_release_regions(pdev); - pci_disable_device(pdev); -} - -static int sc92031_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct sc92031_priv *priv = netdev_priv(dev); - - pci_save_state(pdev); - - if (!netif_running(dev)) - goto out; - - netif_device_detach(dev); - - /* Disable interrupts, stop Tx and Rx. */ - sc92031_disable_interrupts(dev); - - spin_lock(&priv->lock); - - _sc92031_disable_tx_rx(dev); - _sc92031_tx_clear(dev); - mmiowb(); - - spin_unlock(&priv->lock); - -out: - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int sc92031_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct sc92031_priv *priv = netdev_priv(dev); - - pci_restore_state(pdev); - pci_set_power_state(pdev, PCI_D0); - - if (!netif_running(dev)) - goto out; - - /* Interrupts already disabled by sc92031_suspend */ - spin_lock(&priv->lock); - - _sc92031_reset(dev); - mmiowb(); - - spin_unlock(&priv->lock); - sc92031_enable_interrupts(dev); - - netif_device_attach(dev); - - if (netif_carrier_ok(dev)) - netif_wake_queue(dev); - else - netif_tx_disable(dev); - -out: - return 0; -} - -static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = { - { PCI_DEVICE(PCI_VENDOR_ID_SILAN, PCI_DEVICE_ID_SILAN_SC92031) }, - { PCI_DEVICE(PCI_VENDOR_ID_SILAN, PCI_DEVICE_ID_SILAN_8139D) }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table); - -static struct pci_driver sc92031_pci_driver = { - .name = SC92031_NAME, - .id_table = sc92031_pci_device_id_table, - .probe = sc92031_probe, - .remove = __devexit_p(sc92031_remove), - .suspend = sc92031_suspend, - .resume = sc92031_resume, -}; - -static int __init sc92031_init(void) -{ - printk(KERN_INFO SC92031_DESCRIPTION " " SC92031_VERSION "\n"); - return pci_register_driver(&sc92031_pci_driver); -} - -static void __exit sc92031_exit(void) -{ - pci_unregister_driver(&sc92031_pci_driver); -} - -module_init(sc92031_init); -module_exit(sc92031_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Cesar Eduardo Barros "); -MODULE_DESCRIPTION(SC92031_DESCRIPTION); -MODULE_VERSION(SC92031_VERSION); diff --git a/trunk/drivers/net/sk_mca.c b/trunk/drivers/net/sk_mca.c new file mode 100644 index 000000000000..96e06c51b75d --- /dev/null +++ b/trunk/drivers/net/sk_mca.c @@ -0,0 +1,1216 @@ +/* +net-3-driver for the SKNET MCA-based cards + +This is an extension to the Linux operating system, and is covered by the +same GNU General Public License that covers that work. + +Copyright 1999 by Alfred Arnold (alfred@ccac.rwth-aachen.de, + alfred.arnold@lancom.de) + +This driver is based both on the 3C523 driver and the SK_G16 driver. + +paper sources: + 'PC Hardware: Aufbau, Funktionsweise, Programmierung' by + Hans-Peter Messmer for the basic Microchannel stuff + + 'Linux Geraetetreiber' by Allesandro Rubini, Kalle Dalheimer + for help on Ethernet driver programming + + 'Ethernet/IEEE 802.3 Family 1992 World Network Data Book/Handbook' by AMD + for documentation on the AM7990 LANCE + + 'SKNET Personal Technisches Manual', Version 1.2 by Schneider&Koch + for documentation on the Junior board + + 'SK-NET MC2+ Technical Manual", Version 1.1 by Schneider&Koch for + documentation on the MC2 bord + + A big thank you to the S&K support for providing me so quickly with + documentation! + + Also see http://www.syskonnect.com/ + + Missing things: + + -> set debug level via ioctl instead of compile-time switches + -> I didn't follow the development of the 2.1.x kernels, so my + assumptions about which things changed with which kernel version + are probably nonsense + +History: + May 16th, 1999 + startup + May 22st, 1999 + added private structure, methods + begun building data structures in RAM + May 23nd, 1999 + can receive frames, send frames + May 24th, 1999 + modularized initialization of LANCE + loadable as module + still Tx problem :-( + May 26th, 1999 + MC2 works + support for multiple devices + display media type for MC2+ + May 28th, 1999 + fixed problem in GetLANCE leaving interrupts turned off + increase TX queue to 4 packets to improve send performance + May 29th, 1999 + a few corrections in statistics, caught rcvr overruns + reinitialization of LANCE/board in critical situations + MCA info implemented + implemented LANCE multicast filter + Jun 6th, 1999 + additions for Linux 2.2 + Dec 25th, 1999 + unfortunately there seem to be newer MC2+ boards that react + on IRQ 3/5/9/10 instead of 3/5/10/11, so we have to autoprobe + in questionable cases... + Dec 28th, 1999 + integrated patches from David Weinehall & Bill Wendling for 2.3 + kernels (isa_...functions). Things are defined in a way that + it still works with 2.0.x 8-) + Dec 30th, 1999 + added handling of the remaining interrupt conditions. That + should cure the spurious hangs. + Jan 30th, 2000 + newer kernels automatically probe more than one board, so the + 'startslot' as a variable is also needed here + June 1st, 2000 + added changes for recent 2.3 kernels + + *************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define _SK_MCA_DRIVER_ +#include "sk_mca.h" + +/* ------------------------------------------------------------------------ + * global static data - not more since we can handle multiple boards and + * have to pack all state info into the device struct! + * ------------------------------------------------------------------------ */ + +static char *MediaNames[Media_Count] = + { "10Base2", "10BaseT", "10Base5", "Unknown" }; + +static unsigned char poly[] = + { 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 +}; + +/* ------------------------------------------------------------------------ + * private subfunctions + * ------------------------------------------------------------------------ */ + +/* dump parts of shared memory - only needed during debugging */ + +#ifdef DEBUG +static void dumpmem(struct net_device *dev, u32 start, u32 len) +{ + skmca_priv *priv = netdev_priv(dev); + int z; + + for (z = 0; z < len; z++) { + if ((z & 15) == 0) + printk("%04x:", z); + printk(" %02x", readb(priv->base + start + z)); + if ((z & 15) == 15) + printk("\n"); + } +} + +/* print exact time - ditto */ + +static void PrTime(void) +{ + struct timeval tv; + + do_gettimeofday(&tv); + printk("%9d:%06d: ", tv.tv_sec, tv.tv_usec); +} +#endif + +/* deduce resources out of POS registers */ + +static void __init getaddrs(int slot, int junior, int *base, int *irq, + skmca_medium * medium) +{ + u_char pos0, pos1, pos2; + + if (junior) { + pos0 = mca_read_stored_pos(slot, 2); + *base = ((pos0 & 0x0e) << 13) + 0xc0000; + *irq = ((pos0 & 0x10) >> 4) + 10; + *medium = Media_Unknown; + } else { + /* reset POS 104 Bits 0+1 so the shared memory region goes to the + configured area between 640K and 1M. Afterwards, enable the MC2. + I really don't know what rode SK to do this... */ + + mca_write_pos(slot, 4, + mca_read_stored_pos(slot, 4) & 0xfc); + mca_write_pos(slot, 2, + mca_read_stored_pos(slot, 2) | 0x01); + + pos1 = mca_read_stored_pos(slot, 3); + pos2 = mca_read_stored_pos(slot, 4); + *base = ((pos1 & 0x07) << 14) + 0xc0000; + switch (pos2 & 0x0c) { + case 0: + *irq = 3; + break; + case 4: + *irq = 5; + break; + case 8: + *irq = -10; + break; + case 12: + *irq = -11; + break; + } + *medium = (pos2 >> 6) & 3; + } +} + +/* check for both cards: + When the MC2 is turned off, it was configured for more than 15MB RAM, + is disabled and won't get detected using the standard probe. We + therefore have to scan the slots manually :-( */ + +static int __init dofind(int *junior, int firstslot) +{ + int slot; + unsigned int id; + + for (slot = firstslot; slot < MCA_MAX_SLOT_NR; slot++) { + id = mca_read_stored_pos(slot, 0) + + (((unsigned int) mca_read_stored_pos(slot, 1)) << 8); + + *junior = 0; + if (id == SKNET_MCA_ID) + return slot; + *junior = 1; + if (id == SKNET_JUNIOR_MCA_ID) + return slot; + } + return MCA_NOTFOUND; +} + +/* reset the whole board */ + +static void ResetBoard(struct net_device *dev) +{ + skmca_priv *priv = netdev_priv(dev); + + writeb(CTRL_RESET_ON, priv->ctrladdr); + udelay(10); + writeb(CTRL_RESET_OFF, priv->ctrladdr); +} + +/* wait for LANCE interface to become not busy */ + +static int WaitLANCE(struct net_device *dev) +{ + skmca_priv *priv = netdev_priv(dev); + int t = 0; + + while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == + STAT_IO_BUSY) { + udelay(1); + if (++t > 1000) { + printk("%s: LANCE access timeout", dev->name); + return 0; + } + } + + return 1; +} + +/* set LANCE register - must be atomic */ + +static void SetLANCE(struct net_device *dev, u16 addr, u16 value) +{ + skmca_priv *priv = netdev_priv(dev); + unsigned long flags; + + /* disable interrupts */ + + spin_lock_irqsave(&priv->lock, flags); + + /* wait until no transfer is pending */ + + WaitLANCE(dev); + + /* transfer register address to RAP */ + + writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr); + writew(addr, priv->ioregaddr); + writeb(IOCMD_GO, priv->cmdaddr); + udelay(1); + WaitLANCE(dev); + + /* transfer data to register */ + + writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA, priv->ctrladdr); + writew(value, priv->ioregaddr); + writeb(IOCMD_GO, priv->cmdaddr); + udelay(1); + WaitLANCE(dev); + + /* reenable interrupts */ + + spin_unlock_irqrestore(&priv->lock, flags); +} + +/* get LANCE register */ + +static u16 GetLANCE(struct net_device *dev, u16 addr) +{ + skmca_priv *priv = netdev_priv(dev); + unsigned long flags; + unsigned int res; + + /* disable interrupts */ + + spin_lock_irqsave(&priv->lock, flags); + + /* wait until no transfer is pending */ + + WaitLANCE(dev); + + /* transfer register address to RAP */ + + writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr); + writew(addr, priv->ioregaddr); + writeb(IOCMD_GO, priv->cmdaddr); + udelay(1); + WaitLANCE(dev); + + /* transfer data from register */ + + writeb(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA, priv->ctrladdr); + writeb(IOCMD_GO, priv->cmdaddr); + udelay(1); + WaitLANCE(dev); + res = readw(priv->ioregaddr); + + /* reenable interrupts */ + + spin_unlock_irqrestore(&priv->lock, flags); + + return res; +} + +/* build up descriptors in shared RAM */ + +static void InitDscrs(struct net_device *dev) +{ + skmca_priv *priv = netdev_priv(dev); + u32 bufaddr; + + /* Set up Tx descriptors. The board has only 16K RAM so bits 16..23 + are always 0. */ + + bufaddr = RAM_DATABASE; + { + LANCE_TxDescr descr; + int z; + + for (z = 0; z < TXCOUNT; z++) { + descr.LowAddr = bufaddr; + descr.Flags = 0; + descr.Len = 0xf000; + descr.Status = 0; + memcpy_toio(priv->base + RAM_TXBASE + + (z * sizeof(LANCE_TxDescr)), &descr, + sizeof(LANCE_TxDescr)); + memset_io(priv->base + bufaddr, 0, RAM_BUFSIZE); + bufaddr += RAM_BUFSIZE; + } + } + + /* do the same for the Rx descriptors */ + + { + LANCE_RxDescr descr; + int z; + + for (z = 0; z < RXCOUNT; z++) { + descr.LowAddr = bufaddr; + descr.Flags = RXDSCR_FLAGS_OWN; + descr.MaxLen = -RAM_BUFSIZE; + descr.Len = 0; + memcpy_toio(priv->base + RAM_RXBASE + + (z * sizeof(LANCE_RxDescr)), &descr, + sizeof(LANCE_RxDescr)); + memset_io(priv->base + bufaddr, 0, RAM_BUFSIZE); + bufaddr += RAM_BUFSIZE; + } + } +} + +/* calculate the hash bit position for a given multicast address + taken more or less directly from the AMD datasheet... */ + +static void UpdateCRC(unsigned char *CRC, int bit) +{ + int j; + + /* shift CRC one bit */ + + memmove(CRC + 1, CRC, 32 * sizeof(unsigned char)); + CRC[0] = 0; + + /* if bit XOR controlbit = 1, set CRC = CRC XOR polynomial */ + + if (bit ^ CRC[32]) + for (j = 0; j < 32; j++) + CRC[j] ^= poly[j]; +} + +static unsigned int GetHash(char *address) +{ + unsigned char CRC[33]; + int i, byte, hashcode; + + /* a multicast address has bit 0 in the first byte set */ + + if ((address[0] & 1) == 0) + return -1; + + /* initialize CRC */ + + memset(CRC, 1, sizeof(CRC)); + + /* loop through address bits */ + + for (byte = 0; byte < 6; byte++) + for (i = 0; i < 8; i++) + UpdateCRC(CRC, (address[byte] >> i) & 1); + + /* hashcode is the 6 least significant bits of the CRC */ + + hashcode = 0; + for (i = 0; i < 6; i++) + hashcode = (hashcode << 1) + CRC[i]; + return hashcode; +} + +/* feed ready-built initialization block into LANCE */ + +static void InitLANCE(struct net_device *dev) +{ + skmca_priv *priv = netdev_priv(dev); + + /* build up descriptors. */ + + InitDscrs(dev); + + /* next RX descriptor to be read is the first one. Since the LANCE + will start from the beginning after initialization, we have to + reset out pointers too. */ + + priv->nextrx = 0; + + /* no TX descriptors active */ + + priv->nexttxput = priv->nexttxdone = priv->txbusy = 0; + + /* set up the LANCE bus control register - constant for SKnet boards */ + + SetLANCE(dev, LANCE_CSR3, + CSR3_BSWAP_OFF | CSR3_ALE_LOW | CSR3_BCON_HOLD); + + /* write address of initialization block into LANCE */ + + SetLANCE(dev, LANCE_CSR1, RAM_INITBASE & 0xffff); + SetLANCE(dev, LANCE_CSR2, (RAM_INITBASE >> 16) & 0xff); + + /* we don't get ready until the LANCE has read the init block */ + + netif_stop_queue(dev); + + /* let LANCE read the initialization block. LANCE is ready + when we receive the corresponding interrupt. */ + + SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_INIT); +} + +/* stop the LANCE so we can reinitialize it */ + +static void StopLANCE(struct net_device *dev) +{ + /* can't take frames any more */ + + netif_stop_queue(dev); + + /* disable interrupts, stop it */ + + SetLANCE(dev, LANCE_CSR0, CSR0_STOP); +} + +/* initialize card and LANCE for proper operation */ + +static void InitBoard(struct net_device *dev) +{ + skmca_priv *priv = netdev_priv(dev); + LANCE_InitBlock block; + + /* Lay out the shared RAM - first we create the init block for the LANCE. + We do not overwrite it later because we need it again when we switch + promiscous mode on/off. */ + + block.Mode = 0; + if (dev->flags & IFF_PROMISC) + block.Mode |= LANCE_INIT_PROM; + memcpy(block.PAdr, dev->dev_addr, 6); + memset(block.LAdrF, 0, sizeof(block.LAdrF)); + block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29); + block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29); + + memcpy_toio(priv->base + RAM_INITBASE, &block, sizeof(block)); + + /* initialize LANCE. Implicitly sets up other structures in RAM. */ + + InitLANCE(dev); +} + +/* deinitialize card and LANCE */ + +static void DeinitBoard(struct net_device *dev) +{ + /* stop LANCE */ + + StopLANCE(dev); + + /* reset board */ + + ResetBoard(dev); +} + +/* probe for device's irq */ + +static int __init ProbeIRQ(struct net_device *dev) +{ + unsigned long imaskval, njiffies, irq; + u16 csr0val; + + /* enable all interrupts */ + + imaskval = probe_irq_on(); + + /* initialize the board. Wait for interrupt 'Initialization done'. */ + + ResetBoard(dev); + InitBoard(dev); + + njiffies = jiffies + HZ; + do { + csr0val = GetLANCE(dev, LANCE_CSR0); + } + while (((csr0val & CSR0_IDON) == 0) && (jiffies != njiffies)); + + /* turn of interrupts again */ + + irq = probe_irq_off(imaskval); + + /* if we found something, ack the interrupt */ + + if (irq) + SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_IDON); + + /* back to idle state */ + + DeinitBoard(dev); + + return irq; +} + +/* ------------------------------------------------------------------------ + * interrupt handler(s) + * ------------------------------------------------------------------------ */ + +/* LANCE has read initialization block -> start it */ + +static u16 irqstart_handler(struct net_device *dev, u16 oldcsr0) +{ + /* now we're ready to transmit */ + + netif_wake_queue(dev); + + /* reset IDON bit, start LANCE */ + + SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_IDON | CSR0_STRT); + return GetLANCE(dev, LANCE_CSR0); +} + +/* did we lose blocks due to a FIFO overrun ? */ + +static u16 irqmiss_handler(struct net_device *dev, u16 oldcsr0) +{ + skmca_priv *priv = netdev_priv(dev); + + /* update statistics */ + + priv->stat.rx_fifo_errors++; + + /* reset MISS bit */ + + SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_MISS); + return GetLANCE(dev, LANCE_CSR0); +} + +/* receive interrupt */ + +static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0) +{ + skmca_priv *priv = netdev_priv(dev); + LANCE_RxDescr descr; + unsigned int descraddr; + + /* run through queue until we reach a descriptor we do not own */ + + descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr)); + while (1) { + /* read descriptor */ + memcpy_fromio(&descr, priv->base + descraddr, + sizeof(LANCE_RxDescr)); + + /* if we reach a descriptor we do not own, we're done */ + if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0) + break; + +#ifdef DEBUG + PrTime(); + printk("Receive packet on descr %d len %d\n", priv->nextrx, + descr.Len); +#endif + + /* erroneous packet ? */ + if ((descr.Flags & RXDSCR_FLAGS_ERR) != 0) { + priv->stat.rx_errors++; + if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0) + priv->stat.rx_crc_errors++; + else if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0) + priv->stat.rx_frame_errors++; + else if ((descr.Flags & RXDSCR_FLAGS_OFLO) != 0) + priv->stat.rx_fifo_errors++; + } + + /* good packet ? */ + else { + struct sk_buff *skb; + + skb = dev_alloc_skb(descr.Len + 2); + if (skb == NULL) + priv->stat.rx_dropped++; + else { + memcpy_fromio(skb_put(skb, descr.Len), + priv->base + + descr.LowAddr, descr.Len); + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_NONE; + priv->stat.rx_packets++; + priv->stat.rx_bytes += descr.Len; + netif_rx(skb); + dev->last_rx = jiffies; + } + } + + /* give descriptor back to LANCE */ + descr.Len = 0; + descr.Flags |= RXDSCR_FLAGS_OWN; + + /* update descriptor in shared RAM */ + memcpy_toio(priv->base + descraddr, &descr, + sizeof(LANCE_RxDescr)); + + /* go to next descriptor */ + priv->nextrx++; + descraddr += sizeof(LANCE_RxDescr); + if (priv->nextrx >= RXCOUNT) { + priv->nextrx = 0; + descraddr = RAM_RXBASE; + } + } + + /* reset RINT bit */ + + SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_RINT); + return GetLANCE(dev, LANCE_CSR0); +} + +/* transmit interrupt */ + +static u16 irqtx_handler(struct net_device *dev, u16 oldcsr0) +{ + skmca_priv *priv = netdev_priv(dev); + LANCE_TxDescr descr; + unsigned int descraddr; + + /* check descriptors at most until no busy one is left */ + + descraddr = + RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr)); + while (priv->txbusy > 0) { + /* read descriptor */ + memcpy_fromio(&descr, priv->base + descraddr, + sizeof(LANCE_TxDescr)); + + /* if the LANCE still owns this one, we've worked out all sent packets */ + if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0) + break; + +#ifdef DEBUG + PrTime(); + printk("Send packet done on descr %d\n", priv->nexttxdone); +#endif + + /* update statistics */ + if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0) { + priv->stat.tx_packets++; + priv->stat.tx_bytes++; + } else { + priv->stat.tx_errors++; + if ((descr.Status & TXDSCR_STATUS_UFLO) != 0) { + priv->stat.tx_fifo_errors++; + InitLANCE(dev); + } + else + if ((descr.Status & TXDSCR_STATUS_LCOL) != + 0) priv->stat.tx_window_errors++; + else if ((descr.Status & TXDSCR_STATUS_LCAR) != 0) + priv->stat.tx_carrier_errors++; + else if ((descr.Status & TXDSCR_STATUS_RTRY) != 0) + priv->stat.tx_aborted_errors++; + } + + /* go to next descriptor */ + priv->nexttxdone++; + descraddr += sizeof(LANCE_TxDescr); + if (priv->nexttxdone >= TXCOUNT) { + priv->nexttxdone = 0; + descraddr = RAM_TXBASE; + } + priv->txbusy--; + } + + /* reset TX interrupt bit */ + + SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_TINT); + oldcsr0 = GetLANCE(dev, LANCE_CSR0); + + /* at least one descriptor is freed. Therefore we can accept + a new one */ + /* inform upper layers we're in business again */ + + netif_wake_queue(dev); + + return oldcsr0; +} + +/* general interrupt entry */ + +static irqreturn_t irq_handler(int irq, void *device) +{ + struct net_device *dev = (struct net_device *) device; + u16 csr0val; + + /* read CSR0 to get interrupt cause */ + + csr0val = GetLANCE(dev, LANCE_CSR0); + + /* in case we're not meant... */ + + if ((csr0val & CSR0_INTR) == 0) + return IRQ_NONE; + +#if 0 + set_bit(LINK_STATE_RXSEM, &dev->state); +#endif + + /* loop through the interrupt bits until everything is clear */ + + do { + if ((csr0val & CSR0_IDON) != 0) + csr0val = irqstart_handler(dev, csr0val); + if ((csr0val & CSR0_RINT) != 0) + csr0val = irqrx_handler(dev, csr0val); + if ((csr0val & CSR0_MISS) != 0) + csr0val = irqmiss_handler(dev, csr0val); + if ((csr0val & CSR0_TINT) != 0) + csr0val = irqtx_handler(dev, csr0val); + if ((csr0val & CSR0_MERR) != 0) { + SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_MERR); + csr0val = GetLANCE(dev, LANCE_CSR0); + } + if ((csr0val & CSR0_BABL) != 0) { + SetLANCE(dev, LANCE_CSR0, csr0val | CSR0_BABL); + csr0val = GetLANCE(dev, LANCE_CSR0); + } + } + while ((csr0val & CSR0_INTR) != 0); + +#if 0 + clear_bit(LINK_STATE_RXSEM, &dev->state); +#endif + return IRQ_HANDLED; +} + +/* ------------------------------------------------------------------------ + * driver methods + * ------------------------------------------------------------------------ */ + +/* MCA info */ + +static int skmca_getinfo(char *buf, int slot, void *d) +{ + int len = 0, i; + struct net_device *dev = (struct net_device *) d; + skmca_priv *priv; + + /* can't say anything about an uninitialized device... */ + + if (dev == NULL) + return len; + priv = netdev_priv(dev); + + /* print info */ + + len += sprintf(buf + len, "IRQ: %d\n", priv->realirq); + len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start, + dev->mem_end - 1); + len += + sprintf(buf + len, "Transceiver: %s\n", + MediaNames[priv->medium]); + len += sprintf(buf + len, "Device: %s\n", dev->name); + len += sprintf(buf + len, "MAC address:"); + for (i = 0; i < 6; i++) + len += sprintf(buf + len, " %02x", dev->dev_addr[i]); + buf[len++] = '\n'; + buf[len] = 0; + + return len; +} + +/* open driver. Means also initialization and start of LANCE */ + +static int skmca_open(struct net_device *dev) +{ + int result; + skmca_priv *priv = netdev_priv(dev); + + /* register resources - only necessary for IRQ */ + result = + request_irq(priv->realirq, irq_handler, + IRQF_SHARED | IRQF_SAMPLE_RANDOM, "sk_mca", dev); + if (result != 0) { + printk("%s: failed to register irq %d\n", dev->name, + dev->irq); + return result; + } + dev->irq = priv->realirq; + + /* set up the card and LANCE */ + + InitBoard(dev); + + /* set up flags */ + + netif_start_queue(dev); + + return 0; +} + +/* close driver. Shut down board and free allocated resources */ + +static int skmca_close(struct net_device *dev) +{ + /* turn off board */ + DeinitBoard(dev); + + /* release resources */ + if (dev->irq != 0) + free_irq(dev->irq, dev); + dev->irq = 0; + + return 0; +} + +/* transmit a block. */ + +static int skmca_tx(struct sk_buff *skb, struct net_device *dev) +{ + skmca_priv *priv = netdev_priv(dev); + LANCE_TxDescr descr; + unsigned int address; + int tmplen, retval = 0; + unsigned long flags; + + /* if we get called with a NULL descriptor, the Ethernet layer thinks + our card is stuck an we should reset it. We'll do this completely: */ + + if (skb == NULL) { + DeinitBoard(dev); + InitBoard(dev); + return 0; /* don't try to free the block here ;-) */ + } + + /* is there space in the Tx queue ? If no, the upper layer gave us a + packet in spite of us not being ready and is really in trouble. + We'll do the dropping for him: */ + if (priv->txbusy >= TXCOUNT) { + priv->stat.tx_dropped++; + retval = -EIO; + goto tx_done; + } + + /* get TX descriptor */ + address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr)); + memcpy_fromio(&descr, priv->base + address, sizeof(LANCE_TxDescr)); + + /* enter packet length as 2s complement - assure minimum length */ + tmplen = skb->len; + if (tmplen < 60) + tmplen = 60; + descr.Len = 65536 - tmplen; + + /* copy filler into RAM - in case we're filling up... + we're filling a bit more than necessary, but that doesn't harm + since the buffer is far larger... */ + if (tmplen > skb->len) { + char *fill = "NetBSD is a nice OS too! "; + unsigned int destoffs = 0, l = strlen(fill); + + while (destoffs < tmplen) { + memcpy_toio(priv->base + descr.LowAddr + + destoffs, fill, l); + destoffs += l; + } + } + + /* do the real data copying */ + memcpy_toio(priv->base + descr.LowAddr, skb->data, skb->len); + + /* hand descriptor over to LANCE - this is the first and last chunk */ + descr.Flags = + TXDSCR_FLAGS_OWN | TXDSCR_FLAGS_STP | TXDSCR_FLAGS_ENP; + +#ifdef DEBUG + PrTime(); + printk("Send packet on descr %d len %d\n", priv->nexttxput, + skb->len); +#endif + + /* one more descriptor busy */ + + spin_lock_irqsave(&priv->lock, flags); + + priv->nexttxput++; + if (priv->nexttxput >= TXCOUNT) + priv->nexttxput = 0; + priv->txbusy++; + + /* are we saturated ? */ + + if (priv->txbusy >= TXCOUNT) + netif_stop_queue(dev); + + /* write descriptor back to RAM */ + memcpy_toio(priv->base + address, &descr, sizeof(LANCE_TxDescr)); + + /* if no descriptors were active, give the LANCE a hint to read it + immediately */ + + if (priv->txbusy == 0) + SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_TDMD); + + spin_unlock_irqrestore(&priv->lock, flags); + + tx_done: + + dev_kfree_skb(skb); + + return retval; +} + +/* return pointer to Ethernet statistics */ + +static struct net_device_stats *skmca_stats(struct net_device *dev) +{ + skmca_priv *priv = netdev_priv(dev); + + return &(priv->stat); +} + +/* switch receiver mode. We use the LANCE's multicast filter to prefilter + multicast addresses. */ + +static void skmca_set_multicast_list(struct net_device *dev) +{ + skmca_priv *priv = netdev_priv(dev); + LANCE_InitBlock block; + + /* first stop the LANCE... */ + StopLANCE(dev); + + /* ...then modify the initialization block... */ + memcpy_fromio(&block, priv->base + RAM_INITBASE, sizeof(block)); + if (dev->flags & IFF_PROMISC) + block.Mode |= LANCE_INIT_PROM; + else + block.Mode &= ~LANCE_INIT_PROM; + + if (dev->flags & IFF_ALLMULTI) { /* get all multicasts */ + memset(block.LAdrF, 0xff, sizeof(block.LAdrF)); + } else { /* get selected/no multicasts */ + + struct dev_mc_list *mptr; + int code; + + memset(block.LAdrF, 0, sizeof(block.LAdrF)); + for (mptr = dev->mc_list; mptr != NULL; mptr = mptr->next) { + code = GetHash(mptr->dmi_addr); + block.LAdrF[(code >> 3) & 7] |= 1 << (code & 7); + } + } + + memcpy_toio(priv->base + RAM_INITBASE, &block, sizeof(block)); + + /* ...then reinit LANCE with the correct flags */ + InitLANCE(dev); +} + +/* ------------------------------------------------------------------------ + * hardware check + * ------------------------------------------------------------------------ */ + +static int startslot; /* counts through slots when probing multiple devices */ + +static void cleanup_card(struct net_device *dev) +{ + skmca_priv *priv = netdev_priv(dev); + DeinitBoard(dev); + if (dev->irq != 0) + free_irq(dev->irq, dev); + iounmap(priv->base); + mca_mark_as_unused(priv->slot); + mca_set_adapter_procfn(priv->slot, NULL, NULL); +} + +struct net_device * __init skmca_probe(int unit) +{ + struct net_device *dev; + int force_detect = 0; + int junior, slot, i; + int base = 0, irq = 0; + skmca_priv *priv; + skmca_medium medium; + int err; + + /* can't work without an MCA bus ;-) */ + + if (MCA_bus == 0) + return ERR_PTR(-ENODEV); + + dev = alloc_etherdev(sizeof(skmca_priv)); + if (!dev) + return ERR_PTR(-ENOMEM); + + if (unit >= 0) { + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + } + + SET_MODULE_OWNER(dev); + + /* start address of 1 --> forced detection */ + + if (dev->mem_start == 1) + force_detect = 1; + + /* search through slots */ + + base = dev->mem_start; + irq = dev->base_addr; + for (slot = startslot; (slot = dofind(&junior, slot)) != -1; slot++) { + /* deduce card addresses */ + + getaddrs(slot, junior, &base, &irq, &medium); + + /* slot already in use ? */ + + if (mca_is_adapter_used(slot)) + continue; + + /* were we looking for something different ? */ + + if (dev->irq && dev->irq != irq) + continue; + if (dev->mem_start && dev->mem_start != base) + continue; + + /* found something that matches */ + + break; + } + + /* nothing found ? */ + + if (slot == -1) { + free_netdev(dev); + return (base || irq) ? ERR_PTR(-ENXIO) : ERR_PTR(-ENODEV); + } + + /* make procfs entries */ + + if (junior) + mca_set_adapter_name(slot, + "SKNET junior MC2 Ethernet Adapter"); + else + mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter"); + mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev); + + mca_mark_as_used(slot); + + /* announce success */ + printk("%s: SKNet %s adapter found in slot %d\n", dev->name, + junior ? "Junior MC2" : "MC2+", slot + 1); + + priv = netdev_priv(dev); + priv->base = ioremap(base, 0x4000); + if (!priv->base) { + mca_set_adapter_procfn(slot, NULL, NULL); + mca_mark_as_unused(slot); + free_netdev(dev); + return ERR_PTR(-ENOMEM); + } + + priv->slot = slot; + priv->macbase = priv->base + 0x3fc0; + priv->ioregaddr = priv->base + 0x3ff0; + priv->ctrladdr = priv->base + 0x3ff2; + priv->cmdaddr = priv->base + 0x3ff3; + priv->medium = medium; + memset(&priv->stat, 0, sizeof(struct net_device_stats)); + spin_lock_init(&priv->lock); + + /* set base + irq for this device (irq not allocated so far) */ + dev->irq = 0; + dev->mem_start = base; + dev->mem_end = base + 0x4000; + + /* autoprobe ? */ + if (irq < 0) { + int nirq; + + printk + ("%s: ambigous POS bit combination, must probe for IRQ...\n", + dev->name); + nirq = ProbeIRQ(dev); + if (nirq <= 0) + printk("%s: IRQ probe failed, assuming IRQ %d", + dev->name, priv->realirq = -irq); + else + priv->realirq = nirq; + } else + priv->realirq = irq; + + /* set methods */ + dev->open = skmca_open; + dev->stop = skmca_close; + dev->hard_start_xmit = skmca_tx; + dev->do_ioctl = NULL; + dev->get_stats = skmca_stats; + dev->set_multicast_list = skmca_set_multicast_list; + dev->flags |= IFF_MULTICAST; + + /* copy out MAC address */ + for (i = 0; i < 6; i++) + dev->dev_addr[i] = readb(priv->macbase + (i << 1)); + + /* print config */ + printk("%s: IRQ %d, memory %#lx-%#lx, " + "MAC address %02x:%02x:%02x:%02x:%02x:%02x.\n", + dev->name, priv->realirq, dev->mem_start, dev->mem_end - 1, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + printk("%s: %s medium\n", dev->name, MediaNames[priv->medium]); + + /* reset board */ + + ResetBoard(dev); + + startslot = slot + 1; + + err = register_netdev(dev); + if (err) { + cleanup_card(dev); + free_netdev(dev); + dev = ERR_PTR(err); + } + return dev; +} + +/* ------------------------------------------------------------------------ + * modularization support + * ------------------------------------------------------------------------ */ + +#ifdef MODULE +MODULE_LICENSE("GPL"); + +#define DEVMAX 5 + +static struct net_device *moddevs[DEVMAX]; + +int init_module(void) +{ + int z; + + startslot = 0; + for (z = 0; z < DEVMAX; z++) { + struct net_device *dev = skmca_probe(-1); + if (IS_ERR(dev)) + break; + moddevs[z] = dev; + } + if (!z) + return -EIO; + return 0; +} + +void cleanup_module(void) +{ + int z; + + for (z = 0; z < DEVMAX; z++) { + struct net_device *dev = moddevs[z]; + if (dev) { + unregister_netdev(dev); + cleanup_card(dev); + free_netdev(dev); + } + } +} +#endif /* MODULE */ diff --git a/trunk/drivers/net/sk_mca.h b/trunk/drivers/net/sk_mca.h new file mode 100644 index 000000000000..0dae056fed99 --- /dev/null +++ b/trunk/drivers/net/sk_mca.h @@ -0,0 +1,170 @@ +#ifndef _SK_MCA_INCLUDE_ +#define _SK_MCA_INCLUDE_ + +#ifdef _SK_MCA_DRIVER_ + +/* Adapter ID's */ +#define SKNET_MCA_ID 0x6afd +#define SKNET_JUNIOR_MCA_ID 0x6be9 + +/* media enumeration - defined in a way that it fits onto the MC2+'s + POS registers... */ + +typedef enum { Media_10Base2, Media_10BaseT, + Media_10Base5, Media_Unknown, Media_Count +} skmca_medium; + +/* private structure */ +typedef struct { + unsigned int slot; /* MCA-Slot-# */ + void __iomem *base; + void __iomem *macbase; /* base address of MAC address PROM */ + void __iomem *ioregaddr;/* address of I/O-register (Lo) */ + void __iomem *ctrladdr; /* address of control/stat register */ + void __iomem *cmdaddr; /* address of I/O-command register */ + int nextrx; /* index of next RX descriptor to + be read */ + int nexttxput; /* index of next free TX descriptor */ + int nexttxdone; /* index of next TX descriptor to + be finished */ + int txbusy; /* # of busy TX descriptors */ + struct net_device_stats stat; /* packet statistics */ + int realirq; /* memorizes actual IRQ, even when + currently not allocated */ + skmca_medium medium; /* physical cannector */ + spinlock_t lock; +} skmca_priv; + +/* card registers: control/status register bits */ + +#define CTRL_ADR_DATA 0 /* Bit 0 = 0 ->access data register */ +#define CTRL_ADR_RAP 1 /* Bit 0 = 1 ->access RAP register */ +#define CTRL_RW_WRITE 0 /* Bit 1 = 0 ->write register */ +#define CTRL_RW_READ 2 /* Bit 1 = 1 ->read register */ +#define CTRL_RESET_ON 0 /* Bit 3 = 0 ->reset board */ +#define CTRL_RESET_OFF 8 /* Bit 3 = 1 ->no reset of board */ + +#define STAT_ADR_DATA 0 /* Bit 0 of ctrl register read back */ +#define STAT_ADR_RAP 1 +#define STAT_RW_WRITE 0 /* Bit 1 of ctrl register read back */ +#define STAT_RW_READ 2 +#define STAT_RESET_ON 0 /* Bit 3 of ctrl register read back */ +#define STAT_RESET_OFF 8 +#define STAT_IRQ_ACT 0 /* interrupt pending */ +#define STAT_IRQ_NOACT 16 /* no interrupt pending */ +#define STAT_IO_NOBUSY 0 /* no transfer busy */ +#define STAT_IO_BUSY 32 /* transfer busy */ + +/* I/O command register bits */ + +#define IOCMD_GO 128 /* Bit 7 = 1 -> start register xfer */ + +/* LANCE registers */ + +#define LANCE_CSR0 0 /* Status/Control */ + +#define CSR0_ERR 0x8000 /* general error flag */ +#define CSR0_BABL 0x4000 /* transmitter timeout */ +#define CSR0_CERR 0x2000 /* collision error */ +#define CSR0_MISS 0x1000 /* lost Rx block */ +#define CSR0_MERR 0x0800 /* memory access error */ +#define CSR0_RINT 0x0400 /* receiver interrupt */ +#define CSR0_TINT 0x0200 /* transmitter interrupt */ +#define CSR0_IDON 0x0100 /* initialization done */ +#define CSR0_INTR 0x0080 /* general interrupt flag */ +#define CSR0_INEA 0x0040 /* interrupt enable */ +#define CSR0_RXON 0x0020 /* receiver enabled */ +#define CSR0_TXON 0x0010 /* transmitter enabled */ +#define CSR0_TDMD 0x0008 /* force transmission now */ +#define CSR0_STOP 0x0004 /* stop LANCE */ +#define CSR0_STRT 0x0002 /* start LANCE */ +#define CSR0_INIT 0x0001 /* read initialization block */ + +#define LANCE_CSR1 1 /* addr bit 0..15 of initialization */ +#define LANCE_CSR2 2 /* 16..23 block */ + +#define LANCE_CSR3 3 /* Bus control */ +#define CSR3_BCON_HOLD 0 /* Bit 0 = 0 -> BM1,BM0,HOLD */ +#define CSR3_BCON_BUSRQ 1 /* Bit 0 = 1 -> BUSAK0,BYTE,BUSRQ */ +#define CSR3_ALE_HIGH 0 /* Bit 1 = 0 -> ALE asserted high */ +#define CSR3_ALE_LOW 2 /* Bit 1 = 1 -> ALE asserted low */ +#define CSR3_BSWAP_OFF 0 /* Bit 2 = 0 -> no byte swap */ +#define CSR3_BSWAP_ON 4 /* Bit 2 = 1 -> byte swap */ + +/* LANCE structures */ + +typedef struct { /* LANCE initialization block */ + u16 Mode; /* mode flags */ + u8 PAdr[6]; /* MAC address */ + u8 LAdrF[8]; /* Multicast filter */ + u32 RdrP; /* Receive descriptor */ + u32 TdrP; /* Transmit descriptor */ +} LANCE_InitBlock; + +/* Mode flags init block */ + +#define LANCE_INIT_PROM 0x8000 /* enable promiscous mode */ +#define LANCE_INIT_INTL 0x0040 /* internal loopback */ +#define LANCE_INIT_DRTY 0x0020 /* disable retry */ +#define LANCE_INIT_COLL 0x0010 /* force collision */ +#define LANCE_INIT_DTCR 0x0008 /* disable transmit CRC */ +#define LANCE_INIT_LOOP 0x0004 /* loopback */ +#define LANCE_INIT_DTX 0x0002 /* disable transmitter */ +#define LANCE_INIT_DRX 0x0001 /* disable receiver */ + +typedef struct { /* LANCE Tx descriptor */ + u16 LowAddr; /* bit 0..15 of address */ + u16 Flags; /* bit 16..23 of address + Flags */ + u16 Len; /* 2s complement of packet length */ + u16 Status; /* Result of transmission */ +} LANCE_TxDescr; + +#define TXDSCR_FLAGS_OWN 0x8000 /* LANCE owns descriptor */ +#define TXDSCR_FLAGS_ERR 0x4000 /* summary error flag */ +#define TXDSCR_FLAGS_MORE 0x1000 /* more than one retry needed? */ +#define TXDSCR_FLAGS_ONE 0x0800 /* one retry? */ +#define TXDSCR_FLAGS_DEF 0x0400 /* transmission deferred? */ +#define TXDSCR_FLAGS_STP 0x0200 /* first packet in chain? */ +#define TXDSCR_FLAGS_ENP 0x0100 /* last packet in chain? */ + +#define TXDSCR_STATUS_BUFF 0x8000 /* buffer error? */ +#define TXDSCR_STATUS_UFLO 0x4000 /* silo underflow during transmit? */ +#define TXDSCR_STATUS_LCOL 0x1000 /* late collision? */ +#define TXDSCR_STATUS_LCAR 0x0800 /* loss of carrier? */ +#define TXDSCR_STATUS_RTRY 0x0400 /* retry error? */ + +typedef struct { /* LANCE Rx descriptor */ + u16 LowAddr; /* bit 0..15 of address */ + u16 Flags; /* bit 16..23 of address + Flags */ + u16 MaxLen; /* 2s complement of buffer length */ + u16 Len; /* packet length */ +} LANCE_RxDescr; + +#define RXDSCR_FLAGS_OWN 0x8000 /* LANCE owns descriptor */ +#define RXDSCR_FLAGS_ERR 0x4000 /* summary error flag */ +#define RXDSCR_FLAGS_FRAM 0x2000 /* framing error flag */ +#define RXDSCR_FLAGS_OFLO 0x1000 /* FIFO overflow? */ +#define RXDSCR_FLAGS_CRC 0x0800 /* CRC error? */ +#define RXDSCR_FLAGS_BUFF 0x0400 /* buffer error? */ +#define RXDSCR_FLAGS_STP 0x0200 /* first packet in chain? */ +#define RXDCSR_FLAGS_ENP 0x0100 /* last packet in chain? */ + +/* RAM layout */ + +#define TXCOUNT 4 /* length of TX descriptor queue */ +#define LTXCOUNT 2 /* log2 of it */ +#define RXCOUNT 4 /* length of RX descriptor queue */ +#define LRXCOUNT 2 /* log2 of it */ + +#define RAM_INITBASE 0 /* LANCE init block */ +#define RAM_TXBASE 24 /* Start of TX descriptor queue */ +#define RAM_RXBASE \ +(RAM_TXBASE + (TXCOUNT * 8)) /* Start of RX descriptor queue */ +#define RAM_DATABASE \ +(RAM_RXBASE + (RXCOUNT * 8)) /* Start of data area for frames */ +#define RAM_BUFSIZE 1580 /* max. frame size - should never be + reached */ + +#endif /* _SK_MCA_DRIVER_ */ + +#endif /* _SK_MCA_INCLUDE_ */ diff --git a/trunk/drivers/net/skfp/can.c b/trunk/drivers/net/skfp/can.c new file mode 100644 index 000000000000..8a49abce7961 --- /dev/null +++ b/trunk/drivers/net/skfp/can.c @@ -0,0 +1,83 @@ +/****************************************************************************** + * + * (C)Copyright 1998,1999 SysKonnect, + * a business unit of Schneider & Koch & Co. Datensysteme GmbH. + * + * See the file "skfddi.c" for further information. + * + * 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. + * + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +#ifndef lint +static const char xID_sccs[] = "@(#)can.c 1.5 97/04/07 (C) SK " ; +#endif + +/* + * canonical bit order + */ +const u_char canonical[256] = { + 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0, + 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0, + 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8, + 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8, + 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4, + 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4, + 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec, + 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc, + 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2, + 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2, + 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea, + 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa, + 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6, + 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6, + 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee, + 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe, + 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1, + 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1, + 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9, + 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9, + 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5, + 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5, + 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed, + 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd, + 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3, + 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3, + 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb, + 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb, + 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7, + 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7, + 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef, + 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff +} ; + +#ifdef MAKE_TABLE +int byte_reverse(x) +int x ; +{ + int y = 0 ; + + if (x & 0x01) + y |= 0x80 ; + if (x & 0x02) + y |= 0x40 ; + if (x & 0x04) + y |= 0x20 ; + if (x & 0x08) + y |= 0x10 ; + if (x & 0x10) + y |= 0x08 ; + if (x & 0x20) + y |= 0x04 ; + if (x & 0x40) + y |= 0x02 ; + if (x & 0x80) + y |= 0x01 ; + return(y) ; +} +#endif diff --git a/trunk/drivers/net/skfp/drvfbi.c b/trunk/drivers/net/skfp/drvfbi.c index 4fe624b0dd25..5b475833f645 100644 --- a/trunk/drivers/net/skfp/drvfbi.c +++ b/trunk/drivers/net/skfp/drvfbi.c @@ -23,7 +23,6 @@ #include "h/smc.h" #include "h/supern_2.h" #include "h/skfbiinc.h" -#include #ifndef lint static const char ID_sccs[] = "@(#)drvfbi.c 1.63 99/02/11 (C) SK " ; @@ -446,14 +445,16 @@ void read_address(struct s_smc *smc, u_char *mac_addr) char PmdType ; int i ; + extern const u_char canonical[256] ; + #if (defined(ISA) || defined(MCA)) for (i = 0; i < 4 ;i++) { /* read mac address from board */ smc->hw.fddi_phys_addr.a[i] = - bitrev8(inpw(PR_A(i+SA_MAC))); + canonical[(inpw(PR_A(i+SA_MAC))&0xff)] ; } for (i = 4; i < 6; i++) { smc->hw.fddi_phys_addr.a[i] = - bitrev8(inpw(PR_A(i+SA_MAC+PRA_OFF))); + canonical[(inpw(PR_A(i+SA_MAC+PRA_OFF))&0xff)] ; } #endif #ifdef EISA @@ -463,17 +464,17 @@ void read_address(struct s_smc *smc, u_char *mac_addr) */ for (i = 0; i < 4 ;i++) { /* read mac address from board */ smc->hw.fddi_phys_addr.a[i] = - bitrev8(inp(PR_A(i+SA_MAC))); + canonical[inp(PR_A(i+SA_MAC))] ; } for (i = 4; i < 6; i++) { smc->hw.fddi_phys_addr.a[i] = - bitrev8(inp(PR_A(i+SA_MAC+PRA_OFF))); + canonical[inp(PR_A(i+SA_MAC+PRA_OFF))] ; } #endif #ifdef PCI for (i = 0; i < 6; i++) { /* read mac address from board */ smc->hw.fddi_phys_addr.a[i] = - bitrev8(inp(ADDR(B2_MAC_0+i))); + canonical[inp(ADDR(B2_MAC_0+i))] ; } #endif #ifndef PCI @@ -492,7 +493,7 @@ void read_address(struct s_smc *smc, u_char *mac_addr) if (mac_addr) { for (i = 0; i < 6 ;i++) { smc->hw.fddi_canon_addr.a[i] = mac_addr[i] ; - smc->hw.fddi_home_addr.a[i] = bitrev8(mac_addr[i]); + smc->hw.fddi_home_addr.a[i] = canonical[mac_addr[i]] ; } return ; } @@ -500,7 +501,7 @@ void read_address(struct s_smc *smc, u_char *mac_addr) for (i = 0; i < 6 ;i++) { smc->hw.fddi_canon_addr.a[i] = - bitrev8(smc->hw.fddi_phys_addr.a[i]); + canonical[smc->hw.fddi_phys_addr.a[i]] ; } } @@ -1268,8 +1269,11 @@ void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr) { int i ; - for (i = 0 ; i < 6 ; i++) - bia_addr->a[i] = bitrev8(smc->hw.fddi_phys_addr.a[i]); + extern const u_char canonical[256] ; + + for (i = 0 ; i < 6 ; i++) { + bia_addr->a[i] = canonical[smc->hw.fddi_phys_addr.a[i]] ; + } } void smt_start_watchdog(struct s_smc *smc) diff --git a/trunk/drivers/net/skfp/fplustm.c b/trunk/drivers/net/skfp/fplustm.c index a45205da8033..0784f558ca9a 100644 --- a/trunk/drivers/net/skfp/fplustm.c +++ b/trunk/drivers/net/skfp/fplustm.c @@ -22,7 +22,7 @@ #include "h/fddi.h" #include "h/smc.h" #include "h/supern_2.h" -#include +#include "can.c" #ifndef lint static const char ID_sccs[] = "@(#)fplustm.c 1.32 99/02/23 (C) SK " ; @@ -1073,7 +1073,7 @@ static struct s_fpmc* mac_get_mc_table(struct s_smc *smc, if (can) { p = own->a ; for (i = 0 ; i < 6 ; i++, p++) - *p = bitrev8(*p); + *p = canonical[*p] ; } slot = NULL; for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){ diff --git a/trunk/drivers/net/skfp/smt.c b/trunk/drivers/net/skfp/smt.c index fe847800acdc..99a776a51fb5 100644 --- a/trunk/drivers/net/skfp/smt.c +++ b/trunk/drivers/net/skfp/smt.c @@ -18,7 +18,6 @@ #include "h/fddi.h" #include "h/smc.h" #include "h/smt_p.h" -#include #define KERNEL #include "h/smtstate.h" @@ -27,6 +26,8 @@ static const char ID_sccs[] = "@(#)smt.c 2.43 98/11/23 (C) SK " ; #endif +extern const u_char canonical[256] ; + /* * FC in SMbuf */ @@ -179,7 +180,7 @@ void smt_agent_init(struct s_smc *smc) driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ; for (i = 0 ; i < 6 ; i ++) { smc->mib.fddiSMTStationId.sid_node.a[i] = - bitrev8(smc->mib.fddiSMTStationId.sid_node.a[i]); + canonical[smc->mib.fddiSMTStationId.sid_node.a[i]] ; } smc->mib.fddiSMTManufacturerData[0] = smc->mib.fddiSMTStationId.sid_node.a[0] ; @@ -2048,8 +2049,9 @@ static void hwm_conv_can(struct s_smc *smc, char *data, int len) SK_UNUSED(smc) ; - for (i = len; i ; i--, data++) - *data = bitrev8(*data); + for (i = len; i ; i--, data++) { + *data = canonical[*(u_char *)data] ; + } } #endif diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c index e482e7fcbb2b..45283f3f95e4 100644 --- a/trunk/drivers/net/skge.c +++ b/trunk/drivers/net/skge.c @@ -42,7 +42,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.10" +#define DRV_VERSION "1.9" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -132,93 +132,18 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, } /* Wake on Lan only supported on Yukon chips with rev 1 or above */ -static u32 wol_supported(const struct skge_hw *hw) +static int wol_supported(const struct skge_hw *hw) { - if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev != 0) - return WAKE_MAGIC | WAKE_PHY; - else - return 0; -} - -static u32 pci_wake_enabled(struct pci_dev *dev) -{ - int pm = pci_find_capability(dev, PCI_CAP_ID_PM); - u16 value; - - /* If device doesn't support PM Capabilities, but request is to disable - * wake events, it's a nop; otherwise fail */ - if (!pm) - return 0; - - pci_read_config_word(dev, pm + PCI_PM_PMC, &value); - - value &= PCI_PM_CAP_PME_MASK; - value >>= ffs(PCI_PM_CAP_PME_MASK) - 1; /* First bit of mask */ - - return value != 0; -} - -static void skge_wol_init(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - enum pause_control save_mode; - u32 ctrl; - - /* Bring hardware out of reset */ - skge_write16(hw, B0_CTST, CS_RST_CLR); - skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); - - skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); - - /* Force to 10/100 skge_reset will re-enable on resume */ - save_mode = skge->flow_control; - skge->flow_control = FLOW_MODE_SYMMETRIC; - - ctrl = skge->advertising; - skge->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); - - skge_phy_reset(skge); - - skge->flow_control = save_mode; - skge->advertising = ctrl; - - /* Set GMAC to no flow control and auto update for speed/duplex */ - gma_write16(hw, port, GM_GP_CTRL, - GM_GPCR_FC_TX_DIS|GM_GPCR_TX_ENA|GM_GPCR_RX_ENA| - GM_GPCR_DUP_FULL|GM_GPCR_FC_RX_DIS|GM_GPCR_AU_FCT_DIS); - - /* Set WOL address */ - memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR), - skge->netdev->dev_addr, ETH_ALEN); - - /* Turn on appropriate WOL control bits */ - skge_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), WOL_CTL_CLEAR_RESULT); - ctrl = 0; - if (skge->wol & WAKE_PHY) - ctrl |= WOL_CTL_ENA_PME_ON_LINK_CHG|WOL_CTL_ENA_LINK_CHG_UNIT; - else - ctrl |= WOL_CTL_DIS_PME_ON_LINK_CHG|WOL_CTL_DIS_LINK_CHG_UNIT; - - if (skge->wol & WAKE_MAGIC) - ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT; - else - ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT;; - - ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT; - skge_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl); - - /* block receiver */ - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); + return !((hw->chip_id == CHIP_ID_GENESIS || + (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0))); } static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct skge_port *skge = netdev_priv(dev); - wol->supported = wol_supported(skge->hw); - wol->wolopts = skge->wol; + wol->supported = wol_supported(skge->hw) ? WAKE_MAGIC : 0; + wol->wolopts = skge->wol ? WAKE_MAGIC : 0; } static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) @@ -226,12 +151,23 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; - if (wol->wolopts & wol_supported(hw)) + if (wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) return -EOPNOTSUPP; - skge->wol = wol->wolopts; - if (!netif_running(dev)) - skge_wol_init(skge); + if (wol->wolopts == WAKE_MAGIC && !wol_supported(hw)) + return -EOPNOTSUPP; + + skge->wol = wol->wolopts == WAKE_MAGIC; + + if (skge->wol) { + memcpy_toio(hw->regs + WOL_MAC_ADDR, dev->dev_addr, ETH_ALEN); + + skge_write16(hw, WOL_CTRL_STAT, + WOL_CTL_ENA_PME_ON_MAGIC_PKT | + WOL_CTL_ENA_MAGIC_PKT_UNIT); + } else + skge_write16(hw, WOL_CTRL_STAT, WOL_CTL_DEFAULT); + return 0; } @@ -2437,9 +2373,6 @@ static int skge_up(struct net_device *dev) size_t rx_size, tx_size; int err; - if (!is_valid_ether_addr(dev->dev_addr)) - return -EINVAL; - if (netif_msg_ifup(skge)) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); @@ -2459,7 +2392,7 @@ static int skge_up(struct net_device *dev) BUG_ON(skge->dma & 7); if ((u64)skge->dma >> 32 != ((u64) skge->dma + skge->mem_size) >> 32) { - dev_err(&hw->pdev->dev, "pci_alloc_consistent region crosses 4G boundary\n"); + printk(KERN_ERR PFX "pci_alloc_consistent region crosses 4G boundary\n"); err = -EINVAL; goto free_pci_mem; } @@ -3068,7 +3001,6 @@ static void skge_mac_intr(struct skge_hw *hw, int port) /* Handle device specific framing and timeout interrupts */ static void skge_error_irq(struct skge_hw *hw) { - struct pci_dev *pdev = hw->pdev; u32 hwstatus = skge_read32(hw, B0_HWE_ISRC); if (hw->chip_id == CHIP_ID_GENESIS) { @@ -3084,12 +3016,12 @@ static void skge_error_irq(struct skge_hw *hw) } if (hwstatus & IS_RAM_RD_PAR) { - dev_err(&pdev->dev, "Ram read data parity error\n"); + printk(KERN_ERR PFX "Ram read data parity error\n"); skge_write16(hw, B3_RI_CTRL, RI_CLR_RD_PERR); } if (hwstatus & IS_RAM_WR_PAR) { - dev_err(&pdev->dev, "Ram write data parity error\n"); + printk(KERN_ERR PFX "Ram write data parity error\n"); skge_write16(hw, B3_RI_CTRL, RI_CLR_WR_PERR); } @@ -3100,38 +3032,38 @@ static void skge_error_irq(struct skge_hw *hw) skge_mac_parity(hw, 1); if (hwstatus & IS_R1_PAR_ERR) { - dev_err(&pdev->dev, "%s: receive queue parity error\n", - hw->dev[0]->name); + printk(KERN_ERR PFX "%s: receive queue parity error\n", + hw->dev[0]->name); skge_write32(hw, B0_R1_CSR, CSR_IRQ_CL_P); } if (hwstatus & IS_R2_PAR_ERR) { - dev_err(&pdev->dev, "%s: receive queue parity error\n", - hw->dev[1]->name); + printk(KERN_ERR PFX "%s: receive queue parity error\n", + hw->dev[1]->name); skge_write32(hw, B0_R2_CSR, CSR_IRQ_CL_P); } if (hwstatus & (IS_IRQ_MST_ERR|IS_IRQ_STAT)) { u16 pci_status, pci_cmd; - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); + pci_read_config_word(hw->pdev, PCI_COMMAND, &pci_cmd); + pci_read_config_word(hw->pdev, PCI_STATUS, &pci_status); - dev_err(&pdev->dev, "PCI error cmd=%#x status=%#x\n", - pci_cmd, pci_status); + printk(KERN_ERR PFX "%s: PCI error cmd=%#x status=%#x\n", + pci_name(hw->pdev), pci_cmd, pci_status); /* Write the error bits back to clear them. */ pci_status &= PCI_STATUS_ERROR_BITS; skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - pci_write_config_word(pdev, PCI_COMMAND, + pci_write_config_word(hw->pdev, PCI_COMMAND, pci_cmd | PCI_COMMAND_SERR | PCI_COMMAND_PARITY); - pci_write_config_word(pdev, PCI_STATUS, pci_status); + pci_write_config_word(hw->pdev, PCI_STATUS, pci_status); skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); /* if error still set then just ignore it */ hwstatus = skge_read32(hw, B0_HWE_ISRC); if (hwstatus & IS_IRQ_STAT) { - dev_warn(&hw->pdev->dev, "unable to clear error (so ignoring them)\n"); + printk(KERN_INFO PFX "unable to clear error (so ignoring them)\n"); hw->intr_mask &= ~IS_HW_ERR; } } @@ -3345,8 +3277,8 @@ static int skge_reset(struct skge_hw *hw) hw->phy_addr = PHY_ADDR_BCOM; break; default: - dev_err(&hw->pdev->dev, "unsupported phy type 0x%x\n", - hw->phy_type); + printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n", + pci_name(hw->pdev), hw->phy_type); return -EOPNOTSUPP; } break; @@ -3361,8 +3293,8 @@ static int skge_reset(struct skge_hw *hw) break; default: - dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", - hw->chip_id); + printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", + pci_name(hw->pdev), hw->chip_id); return -EOPNOTSUPP; } @@ -3402,7 +3334,7 @@ static int skge_reset(struct skge_hw *hw) /* avoid boards with stuck Hardware error bits */ if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) && (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) { - dev_warn(&hw->pdev->dev, "stuck hardware sensor bit\n"); + printk(KERN_WARNING PFX "stuck hardware sensor bit\n"); hw->intr_mask &= ~IS_HW_ERR; } @@ -3476,7 +3408,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, struct net_device *dev = alloc_etherdev(sizeof(*skge)); if (!dev) { - dev_err(&hw->pdev->dev, "etherdev alloc failed\n"); + printk(KERN_ERR "skge etherdev alloc failed"); return NULL; } @@ -3520,7 +3452,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->duplex = -1; skge->speed = -1; skge->advertising = skge_supported_modes(hw); - skge->wol = pci_wake_enabled(hw->pdev) ? wol_supported(hw) : 0; hw->dev[port] = dev; @@ -3565,13 +3496,15 @@ static int __devinit skge_probe(struct pci_dev *pdev, err = pci_enable_device(pdev); if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); + printk(KERN_ERR PFX "%s cannot enable PCI device\n", + pci_name(pdev)); goto err_out; } err = pci_request_regions(pdev, DRV_NAME); if (err) { - dev_err(&pdev->dev, "cannot obtain PCI resources\n"); + printk(KERN_ERR PFX "%s cannot obtain PCI resources\n", + pci_name(pdev)); goto err_out_disable_pdev; } @@ -3586,7 +3519,8 @@ static int __devinit skge_probe(struct pci_dev *pdev, } if (err) { - dev_err(&pdev->dev, "no usable DMA configuration\n"); + printk(KERN_ERR PFX "%s no usable DMA configuration\n", + pci_name(pdev)); goto err_out_free_regions; } @@ -3604,7 +3538,8 @@ static int __devinit skge_probe(struct pci_dev *pdev, err = -ENOMEM; hw = kzalloc(sizeof(*hw), GFP_KERNEL); if (!hw) { - dev_err(&pdev->dev, "cannot allocate hardware struct\n"); + printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n", + pci_name(pdev)); goto err_out_free_regions; } @@ -3615,7 +3550,8 @@ static int __devinit skge_probe(struct pci_dev *pdev, hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); if (!hw->regs) { - dev_err(&pdev->dev, "cannot map device registers\n"); + printk(KERN_ERR PFX "%s: cannot map device registers\n", + pci_name(pdev)); goto err_out_free_hw; } @@ -3631,19 +3567,23 @@ static int __devinit skge_probe(struct pci_dev *pdev, if (!dev) goto err_out_led_off; - /* Some motherboards are broken and has zero in ROM. */ - if (!is_valid_ether_addr(dev->dev_addr)) - dev_warn(&pdev->dev, "bad (zero?) ethernet address in rom\n"); + if (!is_valid_ether_addr(dev->dev_addr)) { + printk(KERN_ERR PFX "%s: bad (zero?) ethernet address in rom\n", + pci_name(pdev)); + err = -EIO; + goto err_out_free_netdev; + } err = register_netdev(dev); if (err) { - dev_err(&pdev->dev, "cannot register net device\n"); + printk(KERN_ERR PFX "%s: cannot register net device\n", + pci_name(pdev)); goto err_out_free_netdev; } err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, dev->name, hw); if (err) { - dev_err(&pdev->dev, "%s: cannot assign irq %d\n", + printk(KERN_ERR PFX "%s: cannot assign irq %d\n", dev->name, pdev->irq); goto err_out_unregister; } @@ -3654,7 +3594,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, skge_show_addr(dev1); else { /* Failure to register second port need not be fatal */ - dev_warn(&pdev->dev, "register of second port failed\n"); + printk(KERN_WARNING PFX "register of second port failed\n"); hw->dev[1] = NULL; free_netdev(dev1); } @@ -3719,46 +3659,28 @@ static void __devexit skge_remove(struct pci_dev *pdev) } #ifdef CONFIG_PM -static int vaux_avail(struct pci_dev *pdev) -{ - int pm_cap; - - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 ctl; - pci_read_config_word(pdev, pm_cap + PCI_PM_PMC, &ctl); - if (ctl & PCI_PM_CAP_AUX_POWER) - return 1; - } - return 0; -} - - static int skge_suspend(struct pci_dev *pdev, pm_message_t state) { struct skge_hw *hw = pci_get_drvdata(pdev); - int i, err, wol = 0; - - err = pci_save_state(pdev); - if (err) - return err; + int i, wol = 0; + pci_save_state(pdev); for (i = 0; i < hw->ports; i++) { struct net_device *dev = hw->dev[i]; - struct skge_port *skge = netdev_priv(dev); - if (netif_running(dev)) - skge_down(dev); - if (skge->wol) - skge_wol_init(skge); + if (netif_running(dev)) { + struct skge_port *skge = netdev_priv(dev); - wol |= skge->wol; + netif_carrier_off(dev); + if (skge->wol) + netif_stop_queue(dev); + else + skge_down(dev); + wol |= skge->wol; + } + netif_device_detach(dev); } - if (wol && vaux_avail(pdev)) - skge_write8(hw, B0_POWER_CTRL, - PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); - skge_write32(hw, B0_IMSK, 0); pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -3771,14 +3693,8 @@ static int skge_resume(struct pci_dev *pdev) struct skge_hw *hw = pci_get_drvdata(pdev); int i, err; - err = pci_set_power_state(pdev, PCI_D0); - if (err) - goto out; - - err = pci_restore_state(pdev); - if (err) - goto out; - + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); pci_enable_wake(pdev, PCI_D0, 0); err = skge_reset(hw); @@ -3788,6 +3704,7 @@ static int skge_resume(struct pci_dev *pdev) for (i = 0; i < hw->ports; i++) { struct net_device *dev = hw->dev[i]; + netif_device_attach(dev); if (netif_running(dev)) { err = skge_up(dev); diff --git a/trunk/drivers/net/skge.h b/trunk/drivers/net/skge.h index 17b1b479dff5..f6223c533c01 100644 --- a/trunk/drivers/net/skge.h +++ b/trunk/drivers/net/skge.h @@ -876,13 +876,11 @@ enum { WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */ WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */ }; -#define WOL_REGS(port, x) (x + (port)*0x80) enum { WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */ WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */ }; -#define WOL_PATT_RAM_BASE(port) (WOL_PATT_RAM_1 + (port)*0x400) enum { BASE_XMAC_1 = 0x2000,/* XMAC 1 registers */ diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index f2ab3d56e565..822dd0b13133 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -49,7 +49,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.12" +#define DRV_VERSION "1.10" #define PFX DRV_NAME " " /* @@ -105,7 +105,6 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, /* DGE-550SX */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B02) }, /* DGE-560SX */ - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B03) }, /* DGE-550T */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, /* 88E8021 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, /* 88E8022 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, /* 88E8061 */ @@ -127,9 +126,6 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ { 0 } }; @@ -144,7 +140,7 @@ static const u32 portirq_msk[] = { Y2_IS_PORT_1, Y2_IS_PORT_2 }; static const char *yukon2_name[] = { "XL", /* 0xb3 */ "EC Ultra", /* 0xb4 */ - "Extreme", /* 0xb5 */ + "UNKNOWN", /* 0xb5 */ "EC", /* 0xb6 */ "FE", /* 0xb7 */ }; @@ -196,52 +192,76 @@ static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) return v; } - -static void sky2_power_on(struct sky2_hw *hw) +static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) { - /* switch power to VCC (WA for VAUX problem) */ - sky2_write8(hw, B0_POWER_CTRL, - PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); + u16 power_control; + int vaux; - /* disable Core Clock Division, */ - sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); + pr_debug("sky2_set_power_state %d\n", state); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) - /* enable bits are inverted */ - sky2_write8(hw, B2_Y2_CLK_GATE, - Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | - Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | - Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); - else - sky2_write8(hw, B2_Y2_CLK_GATE, 0); + power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_PMC); + vaux = (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) && + (power_control & PCI_PM_CAP_PME_D3cold); - if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { - u32 reg1; + power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_CTRL); - sky2_pci_write32(hw, PCI_DEV_REG3, 0); - reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); - reg1 &= P_ASPM_CONTROL_MSK; - sky2_pci_write32(hw, PCI_DEV_REG4, reg1); - sky2_pci_write32(hw, PCI_DEV_REG5, 0); - } -} + power_control |= PCI_PM_CTRL_PME_STATUS; + power_control &= ~(PCI_PM_CTRL_STATE_MASK); -static void sky2_power_aux(struct sky2_hw *hw) -{ - if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) - sky2_write8(hw, B2_Y2_CLK_GATE, 0); - else - /* enable bits are inverted */ - sky2_write8(hw, B2_Y2_CLK_GATE, - Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | - Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | - Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); - - /* switch power to VAUX */ - if (sky2_read16(hw, B0_CTST) & Y2_VAUX_AVAIL) + switch (state) { + case PCI_D0: + /* switch power to VCC (WA for VAUX problem) */ sky2_write8(hw, B0_POWER_CTRL, - (PC_VAUX_ENA | PC_VCC_ENA | - PC_VAUX_ON | PC_VCC_OFF)); + PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); + + /* disable Core Clock Division, */ + sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); + + if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) + /* enable bits are inverted */ + sky2_write8(hw, B2_Y2_CLK_GATE, + Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | + Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | + Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); + else + sky2_write8(hw, B2_Y2_CLK_GATE, 0); + + if (hw->chip_id == CHIP_ID_YUKON_EC_U) { + u32 reg1; + + sky2_pci_write32(hw, PCI_DEV_REG3, 0); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); + reg1 &= P_ASPM_CONTROL_MSK; + sky2_pci_write32(hw, PCI_DEV_REG4, reg1); + sky2_pci_write32(hw, PCI_DEV_REG5, 0); + } + + break; + + case PCI_D3hot: + case PCI_D3cold: + if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) + sky2_write8(hw, B2_Y2_CLK_GATE, 0); + else + /* enable bits are inverted */ + sky2_write8(hw, B2_Y2_CLK_GATE, + Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | + Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | + Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); + + /* switch power to VAUX */ + if (vaux && state != PCI_D3cold) + sky2_write8(hw, B0_POWER_CTRL, + (PC_VAUX_ENA | PC_VCC_ENA | + PC_VAUX_ON | PC_VCC_OFF)); + break; + default: + printk(KERN_ERR PFX "Unknown power state %d\n", state); + } + + sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control); + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); } static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) @@ -293,10 +313,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) struct sky2_port *sky2 = netdev_priv(hw->dev[port]); u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; - if (sky2->autoneg == AUTONEG_ENABLE - && !(hw->chip_id == CHIP_ID_YUKON_XL - || hw->chip_id == CHIP_ID_YUKON_EC_U - || hw->chip_id == CHIP_ID_YUKON_EX)) { + if (sky2->autoneg == AUTONEG_ENABLE && + !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | @@ -323,10 +341,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* enable automatic crossover */ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); - if (sky2->autoneg == AUTONEG_ENABLE - && (hw->chip_id == CHIP_ID_YUKON_XL - || hw->chip_id == CHIP_ID_YUKON_EC_U - || hw->chip_id == CHIP_ID_YUKON_EX)) { + if (sky2->autoneg == AUTONEG_ENABLE && + (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { ctrl &= ~PHY_M_PC_DSC_MSK; ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; } @@ -481,9 +497,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* restore page register */ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); break; - case CHIP_ID_YUKON_EC_U: - case CHIP_ID_YUKON_EX: pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); /* select page 3 to access LED control register */ @@ -525,7 +539,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* set page register to 0 */ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); - } else if (hw->chip_id != CHIP_ID_YUKON_EX) { + } else { gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { @@ -577,73 +591,6 @@ static void sky2_phy_reinit(struct sky2_port *sky2) spin_unlock_bh(&sky2->phy_lock); } -/* Put device in state to listen for Wake On Lan */ -static void sky2_wol_init(struct sky2_port *sky2) -{ - struct sky2_hw *hw = sky2->hw; - unsigned port = sky2->port; - enum flow_control save_mode; - u16 ctrl; - u32 reg1; - - /* Bring hardware out of reset */ - sky2_write16(hw, B0_CTST, CS_RST_CLR); - sky2_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); - - sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); - sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); - - /* Force to 10/100 - * sky2_reset will re-enable on resume - */ - save_mode = sky2->flow_mode; - ctrl = sky2->advertising; - - sky2->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); - sky2->flow_mode = FC_NONE; - sky2_phy_power(hw, port, 1); - sky2_phy_reinit(sky2); - - sky2->flow_mode = save_mode; - sky2->advertising = ctrl; - - /* Set GMAC to no flow control and auto update for speed/duplex */ - gma_write16(hw, port, GM_GP_CTRL, - GM_GPCR_FC_TX_DIS|GM_GPCR_TX_ENA|GM_GPCR_RX_ENA| - GM_GPCR_DUP_FULL|GM_GPCR_FC_RX_DIS|GM_GPCR_AU_FCT_DIS); - - /* Set WOL address */ - memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR), - sky2->netdev->dev_addr, ETH_ALEN); - - /* Turn on appropriate WOL control bits */ - sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), WOL_CTL_CLEAR_RESULT); - ctrl = 0; - if (sky2->wol & WAKE_PHY) - ctrl |= WOL_CTL_ENA_PME_ON_LINK_CHG|WOL_CTL_ENA_LINK_CHG_UNIT; - else - ctrl |= WOL_CTL_DIS_PME_ON_LINK_CHG|WOL_CTL_DIS_LINK_CHG_UNIT; - - if (sky2->wol & WAKE_MAGIC) - ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT; - else - ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT;; - - ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT; - sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl); - - /* Turn on legacy PCI-Express PME mode */ - sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); - reg1 |= PCI_Y2_PME_LEGACY; - sky2_pci_write32(hw, PCI_DEV_REG1, reg1); - sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - /* block receiver */ - sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); - -} - static void sky2_mac_init(struct sky2_hw *hw, unsigned port) { struct sky2_port *sky2 = netdev_priv(hw->dev[port]); @@ -737,7 +684,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); - if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { + if (hw->chip_id == CHIP_ID_YUKON_EC_U) { sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); if (hw->dev[port]->mtu > ETH_DATA_LEN) { @@ -1520,9 +1467,6 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) if (unlikely(netif_msg_tx_done(sky2))) printk(KERN_DEBUG "%s: tx done %u\n", dev->name, idx); - sky2->net_stats.tx_packets++; - sky2->net_stats.tx_bytes += re->skb->len; - dev_kfree_skb_any(re->skb); } @@ -1697,9 +1641,7 @@ static void sky2_link_up(struct sky2_port *sky2) sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); - if (hw->chip_id == CHIP_ID_YUKON_XL - || hw->chip_id == CHIP_ID_YUKON_EC_U - || hw->chip_id == CHIP_ID_YUKON_EX) { + if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) { u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ @@ -1792,16 +1734,14 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; /* Pause bits are offset (9..8) */ - if (hw->chip_id == CHIP_ID_YUKON_XL - || hw->chip_id == CHIP_ID_YUKON_EC_U - || hw->chip_id == CHIP_ID_YUKON_EX) + if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) aux >>= 6; sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN, aux & PHY_M_PS_TX_P_EN); if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000 - && !(hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)) + && hw->chip_id != CHIP_ID_YUKON_EC_U) sky2->flow_status = FC_NONE; if (aux & PHY_M_PS_RX_P_EN) @@ -1854,37 +1794,48 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) } -/* Transmit timeout is only called if we are running, carrier is up +/* Transmit timeout is only called if we are running, carries is up * and tx queue is full (stopped). - * Called with netif_tx_lock held. */ static void sky2_tx_timeout(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; - u32 imask; + unsigned txq = txqaddr[sky2->port]; + u16 report, done; if (netif_msg_timer(sky2)) printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); + report = sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX); + done = sky2_read16(hw, Q_ADDR(txq, Q_DONE)); + printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", - dev->name, sky2->tx_cons, sky2->tx_prod, - sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), - sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE))); + dev->name, + sky2->tx_cons, sky2->tx_prod, report, done); - imask = sky2_read32(hw, B0_IMSK); /* block IRQ in hw */ - sky2_write32(hw, B0_IMSK, 0); - sky2_read32(hw, B0_IMSK); + if (report != done) { + printk(KERN_INFO PFX "status burst pending (irq moderation?)\n"); - netif_poll_disable(hw->dev[0]); /* stop NAPI poll */ - synchronize_irq(hw->pdev->irq); + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); + } else if (report != sky2->tx_cons) { + printk(KERN_INFO PFX "status report lost?\n"); - netif_start_queue(dev); /* don't wakeup during flush */ - sky2_tx_complete(sky2, sky2->tx_prod); /* Flush transmit queue */ + netif_tx_lock_bh(dev); + sky2_tx_complete(sky2, report); + netif_tx_unlock_bh(dev); + } else { + printk(KERN_INFO PFX "hardware hung? flushing\n"); - sky2_write32(hw, B0_IMSK, imask); + sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); + sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); + + sky2_tx_clean(dev); - sky2_phy_reinit(sky2); /* this clears flow control etc */ + sky2_qset(hw, txq); + sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); + } } static int sky2_change_mtu(struct net_device *dev, int new_mtu) @@ -1898,9 +1849,8 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; - /* TSO on Yukon Ultra and MTU > 1500 not supported */ if (hw->chip_id == CHIP_ID_YUKON_EC_U && new_mtu > ETH_DATA_LEN) - dev->features &= ~NETIF_F_TSO; + return -EINVAL; if (!netif_running(dev)) { dev->mtu = new_mtu; @@ -2139,8 +2089,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) goto force_update; skb->protocol = eth_type_trans(skb, dev); - sky2->net_stats.rx_packets++; - sky2->net_stats.rx_bytes += skb->len; dev->last_rx = jiffies; #ifdef SKY2_VLAN_TAG_USED @@ -2270,8 +2218,8 @@ static void sky2_hw_intr(struct sky2_hw *hw) pci_err = sky2_pci_read16(hw, PCI_STATUS); if (net_ratelimit()) - dev_err(&hw->pdev->dev, "PCI hardware error (0x%x)\n", - pci_err); + printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n", + pci_name(hw->pdev), pci_err); sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); sky2_pci_write16(hw, PCI_STATUS, @@ -2286,8 +2234,8 @@ static void sky2_hw_intr(struct sky2_hw *hw) pex_err = sky2_pci_read32(hw, PEX_UNC_ERR_STAT); if (net_ratelimit()) - dev_err(&hw->pdev->dev, "PCI Express error (0x%x)\n", - pex_err); + printk(KERN_ERR PFX "%s: pci express error (0x%x)\n", + pci_name(hw->pdev), pex_err); /* clear the interrupt */ sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); @@ -2456,7 +2404,6 @@ static inline u32 sky2_mhz(const struct sky2_hw *hw) switch (hw->chip_id) { case CHIP_ID_YUKON_EC: case CHIP_ID_YUKON_EC_U: - case CHIP_ID_YUKON_EX: return 125; /* 125 Mhz */ case CHIP_ID_YUKON_FE: return 100; /* 100 Mhz */ @@ -2476,62 +2423,34 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) } -static int __devinit sky2_init(struct sky2_hw *hw) +static int sky2_reset(struct sky2_hw *hw) { + u16 status; u8 t8; + int i; sky2_write8(hw, B0_CTST, CS_RST_CLR); hw->chip_id = sky2_read8(hw, B2_CHIP_ID); if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { - dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", - hw->chip_id); + printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", + pci_name(hw->pdev), hw->chip_id); return -EOPNOTSUPP; } - if (hw->chip_id == CHIP_ID_YUKON_EX) - dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n" - "Please report success or failure to \n"); - - /* Make sure and enable all clocks */ - if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) - sky2_pci_write32(hw, PCI_DEV_REG3, 0); - hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; /* This rev is really old, and requires untested workarounds */ if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) { - dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n", - yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], - hw->chip_id, hw->chip_rev); + printk(KERN_ERR PFX "%s: unsupported revision Yukon-%s (0x%x) rev %d\n", + pci_name(hw->pdev), yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], + hw->chip_id, hw->chip_rev); return -EOPNOTSUPP; } - hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); - hw->ports = 1; - t8 = sky2_read8(hw, B2_Y2_HW_RES); - if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { - if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) - ++hw->ports; - } - - return 0; -} - -static void sky2_reset(struct sky2_hw *hw) -{ - u16 status; - int i; - /* disable ASF */ if (hw->chip_id <= CHIP_ID_YUKON_EC) { - if (hw->chip_id == CHIP_ID_YUKON_EX) { - status = sky2_read16(hw, HCU_CCSR); - status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE | - HCU_CCSR_UC_STATE_MSK); - sky2_write16(hw, HCU_CCSR, status); - } else - sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); + sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); } @@ -2553,7 +2472,15 @@ static void sky2_reset(struct sky2_hw *hw) sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); - sky2_power_on(hw); + hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); + hw->ports = 1; + t8 = sky2_read8(hw, B2_Y2_HW_RES); + if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { + if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) + ++hw->ports; + } + + sky2_set_power_state(hw, PCI_D0); for (i = 0; i < hw->ports; i++) { sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); @@ -2636,37 +2563,7 @@ static void sky2_reset(struct sky2_hw *hw) sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); -} - -static inline u8 sky2_wol_supported(const struct sky2_hw *hw) -{ - return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0; -} - -static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - const struct sky2_port *sky2 = netdev_priv(dev); - - wol->supported = sky2_wol_supported(sky2->hw); - wol->wolopts = sky2->wol; -} - -static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct sky2_port *sky2 = netdev_priv(dev); - struct sky2_hw *hw = sky2->hw; - - if (wol->wolopts & ~sky2_wol_supported(sky2->hw)) - return -EOPNOTSUPP; - - sky2->wol = wol->wolopts; - - if (hw->chip_id == CHIP_ID_YUKON_EC_U) - sky2_write32(hw, B0_CTST, sky2->wol - ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); - if (!netif_running(dev)) - sky2_wol_init(sky2); return 0; } @@ -2917,9 +2814,25 @@ static void sky2_get_strings(struct net_device *dev, u32 stringset, u8 * data) } } +/* Use hardware MIB variables for critical path statistics and + * transmit feedback not reported at interrupt. + * Other errors are accounted for in interrupt handler. + */ static struct net_device_stats *sky2_get_stats(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); + u64 data[13]; + + sky2_phy_stats(sky2, data, ARRAY_SIZE(data)); + + sky2->net_stats.tx_bytes = data[0]; + sky2->net_stats.rx_bytes = data[1]; + sky2->net_stats.tx_packets = data[2] + data[4] + data[6]; + sky2->net_stats.rx_packets = data[3] + data[5] + data[7]; + sky2->net_stats.multicast = data[3] + data[5]; + sky2->net_stats.collisions = data[10]; + sky2->net_stats.tx_aborted_errors = data[12]; + return &sky2->net_stats; } @@ -3278,9 +3191,7 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, static const struct ethtool_ops sky2_ethtool_ops = { .get_settings = sky2_get_settings, .set_settings = sky2_set_settings, - .get_drvinfo = sky2_get_drvinfo, - .get_wol = sky2_get_wol, - .set_wol = sky2_set_wol, + .get_drvinfo = sky2_get_drvinfo, .get_msglevel = sky2_get_msglevel, .set_msglevel = sky2_set_msglevel, .nway_reset = sky2_nway_reset, @@ -3310,14 +3221,13 @@ static const struct ethtool_ops sky2_ethtool_ops = { /* Initialize network device */ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, - unsigned port, - int highmem, int wol) + unsigned port, int highmem) { struct sky2_port *sky2; struct net_device *dev = alloc_etherdev(sizeof(*sky2)); if (!dev) { - dev_err(&hw->pdev->dev, "etherdev alloc failed"); + printk(KERN_ERR "sky2 etherdev alloc failed"); return NULL; } @@ -3359,7 +3269,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->speed = -1; sky2->advertising = sky2_supported_modes(hw); sky2->rx_csum = 1; - sky2->wol = wol; spin_lock_init(&sky2->phy_lock); sky2->tx_pending = TX_DEF_PENDING; @@ -3369,9 +3278,11 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->port = port; - dev->features |= NETIF_F_TSO | NETIF_F_IP_CSUM | NETIF_F_SG; + if (hw->chip_id != CHIP_ID_YUKON_EC_U) + dev->features |= NETIF_F_TSO; if (highmem) dev->features |= NETIF_F_HIGHDMA; + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; #ifdef SKY2_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; @@ -3432,7 +3343,8 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) err = request_irq(pdev->irq, sky2_test_intr, 0, DRV_NAME, hw); if (err) { - dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); + printk(KERN_ERR PFX "%s: cannot assign irq %d\n", + pci_name(pdev), pdev->irq); return err; } @@ -3443,8 +3355,9 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) if (!hw->msi) { /* MSI test failed, go back to INTx mode */ - dev_info(&pdev->dev, "No interrupt generated using MSI, " - "switching to INTx mode.\n"); + printk(KERN_INFO PFX "%s: No interrupt generated using MSI, " + "switching to INTx mode.\n", + pci_name(pdev)); err = -EOPNOTSUPP; sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); @@ -3458,62 +3371,62 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) return err; } -static int __devinit pci_wake_enabled(struct pci_dev *dev) -{ - int pm = pci_find_capability(dev, PCI_CAP_ID_PM); - u16 value; - - if (!pm) - return 0; - if (pci_read_config_word(dev, pm + PCI_PM_CTRL, &value)) - return 0; - return value & PCI_PM_CTRL_PME_ENABLE; -} - static int __devinit sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct net_device *dev; + struct net_device *dev, *dev1 = NULL; struct sky2_hw *hw; - int err, using_dac = 0, wol_default; + int err, pm_cap, using_dac = 0; err = pci_enable_device(pdev); if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); + printk(KERN_ERR PFX "%s cannot enable PCI device\n", + pci_name(pdev)); goto err_out; } err = pci_request_regions(pdev, DRV_NAME); if (err) { - dev_err(&pdev->dev, "cannot obtain PCI resources\n"); + printk(KERN_ERR PFX "%s cannot obtain PCI resources\n", + pci_name(pdev)); goto err_out; } pci_set_master(pdev); + /* Find power-management capability. */ + pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); + if (pm_cap == 0) { + printk(KERN_ERR PFX "Cannot find PowerManagement capability, " + "aborting.\n"); + err = -EIO; + goto err_out_free_regions; + } + if (sizeof(dma_addr_t) > sizeof(u32) && !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { using_dac = 1; err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); if (err < 0) { - dev_err(&pdev->dev, "unable to obtain 64 bit DMA " - "for consistent allocations\n"); + printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA " + "for consistent allocations\n", pci_name(pdev)); goto err_out_free_regions; } + } else { err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (err) { - dev_err(&pdev->dev, "no usable DMA configuration\n"); + printk(KERN_ERR PFX "%s no usable DMA configuration\n", + pci_name(pdev)); goto err_out_free_regions; } } - wol_default = pci_wake_enabled(pdev) ? WAKE_MAGIC : 0; - err = -ENOMEM; hw = kzalloc(sizeof(*hw), GFP_KERNEL); if (!hw) { - dev_err(&pdev->dev, "cannot allocate hardware struct\n"); + printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n", + pci_name(pdev)); goto err_out_free_regions; } @@ -3521,9 +3434,11 @@ static int __devinit sky2_probe(struct pci_dev *pdev, hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); if (!hw->regs) { - dev_err(&pdev->dev, "cannot map device registers\n"); + printk(KERN_ERR PFX "%s: cannot map device registers\n", + pci_name(pdev)); goto err_out_free_hw; } + hw->pm_cap = pm_cap; #ifdef __BIG_ENDIAN /* The sk98lin vendor driver uses hardware byte swapping but @@ -3543,22 +3458,18 @@ static int __devinit sky2_probe(struct pci_dev *pdev, if (!hw->st_le) goto err_out_iounmap; - err = sky2_init(hw); + err = sky2_reset(hw); if (err) goto err_out_iounmap; - dev_info(&pdev->dev, "v%s addr 0x%llx irq %d Yukon-%s (0x%x) rev %d\n", + printk(KERN_INFO PFX "v%s addr 0x%llx irq %d Yukon-%s (0x%x) rev %d\n", DRV_VERSION, (unsigned long long)pci_resource_start(pdev, 0), pdev->irq, yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], hw->chip_id, hw->chip_rev); - sky2_reset(hw); - - dev = sky2_init_netdev(hw, 0, using_dac, wol_default); - if (!dev) { - err = -ENOMEM; + dev = sky2_init_netdev(hw, 0, using_dac); + if (!dev) goto err_out_free_pci; - } if (!disable_msi && pci_enable_msi(pdev) == 0) { err = sky2_test_msi(hw); @@ -3570,33 +3481,32 @@ static int __devinit sky2_probe(struct pci_dev *pdev, err = register_netdev(dev); if (err) { - dev_err(&pdev->dev, "cannot register net device\n"); + printk(KERN_ERR PFX "%s: cannot register net device\n", + pci_name(pdev)); goto err_out_free_netdev; } err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED, dev->name, hw); if (err) { - dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); + printk(KERN_ERR PFX "%s: cannot assign irq %d\n", + pci_name(pdev), pdev->irq); goto err_out_unregister; } sky2_write32(hw, B0_IMSK, Y2_IS_BASE); sky2_show_addr(dev); - if (hw->ports > 1) { - struct net_device *dev1; - - dev1 = sky2_init_netdev(hw, 1, using_dac, wol_default); - if (!dev1) - dev_warn(&pdev->dev, "allocation for second device failed\n"); - else if ((err = register_netdev(dev1))) { - dev_warn(&pdev->dev, - "register of second port failed (%d)\n", err); + if (hw->ports > 1 && (dev1 = sky2_init_netdev(hw, 1, using_dac))) { + if (register_netdev(dev1) == 0) + sky2_show_addr(dev1); + else { + /* Failure to register second port need not be fatal */ + printk(KERN_WARNING PFX + "register of second port failed\n"); hw->dev[1] = NULL; free_netdev(dev1); - } else - sky2_show_addr(dev1); + } } setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); @@ -3645,8 +3555,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) unregister_netdev(dev1); unregister_netdev(dev0); - sky2_power_aux(hw); - + sky2_set_power_state(hw, PCI_D3hot); sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); sky2_write8(hw, B0_CTST, CS_RST_SET); sky2_read8(hw, B0_CTST); @@ -3671,31 +3580,27 @@ static void __devexit sky2_remove(struct pci_dev *pdev) static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) { struct sky2_hw *hw = pci_get_drvdata(pdev); - int i, wol = 0; + int i; + pci_power_t pstate = pci_choose_state(pdev, state); + + if (!(pstate == PCI_D3hot || pstate == PCI_D3cold)) + return -EINVAL; del_timer_sync(&hw->idle_timer); netif_poll_disable(hw->dev[0]); for (i = 0; i < hw->ports; i++) { struct net_device *dev = hw->dev[i]; - struct sky2_port *sky2 = netdev_priv(dev); - if (netif_running(dev)) + if (netif_running(dev)) { sky2_down(dev); - - if (sky2->wol) - sky2_wol_init(sky2); - - wol |= sky2->wol; + netif_device_detach(dev); + } } sky2_write32(hw, B0_IMSK, 0); - sky2_power_aux(hw); - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - + sky2_set_power_state(hw, pstate); return 0; } @@ -3704,22 +3609,21 @@ static int sky2_resume(struct pci_dev *pdev) struct sky2_hw *hw = pci_get_drvdata(pdev); int i, err; - err = pci_set_power_state(pdev, PCI_D0); - if (err) - goto out; + pci_restore_state(pdev); + pci_enable_wake(pdev, PCI_D0, 0); + sky2_set_power_state(hw, PCI_D0); - err = pci_restore_state(pdev); + err = sky2_reset(hw); if (err) goto out; - pci_enable_wake(pdev, PCI_D0, 0); - sky2_reset(hw); - sky2_write32(hw, B0_IMSK, Y2_IS_BASE); for (i = 0; i < hw->ports; i++) { struct net_device *dev = hw->dev[i]; if (netif_running(dev)) { + netif_device_attach(dev); + err = sky2_up(dev); if (err) { printk(KERN_ERR PFX "%s: could not up: %d\n", @@ -3732,43 +3636,11 @@ static int sky2_resume(struct pci_dev *pdev) netif_poll_enable(hw->dev[0]); sky2_idle_start(hw); - return 0; out: - dev_err(&pdev->dev, "resume failed (%d)\n", err); - pci_disable_device(pdev); return err; } #endif -static void sky2_shutdown(struct pci_dev *pdev) -{ - struct sky2_hw *hw = pci_get_drvdata(pdev); - int i, wol = 0; - - del_timer_sync(&hw->idle_timer); - netif_poll_disable(hw->dev[0]); - - for (i = 0; i < hw->ports; i++) { - struct net_device *dev = hw->dev[i]; - struct sky2_port *sky2 = netdev_priv(dev); - - if (sky2->wol) { - wol = 1; - sky2_wol_init(sky2); - } - } - - if (wol) - sky2_power_aux(hw); - - pci_enable_wake(pdev, PCI_D3hot, wol); - pci_enable_wake(pdev, PCI_D3cold, wol); - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - -} - static struct pci_driver sky2_driver = { .name = DRV_NAME, .id_table = sky2_id_table, @@ -3778,7 +3650,6 @@ static struct pci_driver sky2_driver = { .suspend = sky2_suspend, .resume = sky2_resume, #endif - .shutdown = sky2_shutdown, }; static int __init sky2_init_module(void) diff --git a/trunk/drivers/net/sky2.h b/trunk/drivers/net/sky2.h index 3b0189569d52..6ed1d47dbbd3 100644 --- a/trunk/drivers/net/sky2.h +++ b/trunk/drivers/net/sky2.h @@ -32,7 +32,6 @@ enum pci_dev_reg_1 { PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */ PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */ PCI_Y2_PHY1_POWD = 1<<26, /* Set PHY 1 to Power Down (YUKON-2) */ - PCI_Y2_PME_LEGACY= 1<<15, /* PCI Express legacy power management mode */ }; enum pci_dev_reg_2 { @@ -371,9 +370,12 @@ enum { /* B2_CHIP_ID 8 bit Chip Identification Number */ enum { + CHIP_ID_GENESIS = 0x0a, /* Chip ID for GENESIS */ + CHIP_ID_YUKON = 0xb0, /* Chip ID for YUKON */ + CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */ + CHIP_ID_YUKON_LP = 0xb2, /* Chip ID for YUKON-LP */ CHIP_ID_YUKON_XL = 0xb3, /* Chip ID for YUKON-2 XL */ CHIP_ID_YUKON_EC_U = 0xb4, /* Chip ID for YUKON-2 EC Ultra */ - CHIP_ID_YUKON_EX = 0xb5, /* Chip ID for YUKON-2 Extreme */ CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */ CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */ @@ -765,24 +767,6 @@ enum { POLL_LIST_ADDR_HI= 0x0e2c,/* 32 bit Poll. List Start Addr (high) */ }; -enum { - SMB_CFG = 0x0e40, /* 32 bit SMBus Config Register */ - SMB_CSR = 0x0e44, /* 32 bit SMBus Control/Status Register */ -}; - -enum { - CPU_WDOG = 0x0e48, /* 32 bit Watchdog Register */ - CPU_CNTR = 0x0e4C, /* 32 bit Counter Register */ - CPU_TIM = 0x0e50,/* 32 bit Timer Compare Register */ - CPU_AHB_ADDR = 0x0e54, /* 32 bit CPU AHB Debug Register */ - CPU_AHB_WDATA = 0x0e58, /* 32 bit CPU AHB Debug Register */ - CPU_AHB_RDATA = 0x0e5C, /* 32 bit CPU AHB Debug Register */ - HCU_MAP_BASE = 0x0e60, /* 32 bit Reset Mapping Base */ - CPU_AHB_CTRL = 0x0e64, /* 32 bit CPU AHB Debug Register */ - HCU_CCSR = 0x0e68, /* 32 bit CPU Control and Status Register */ - HCU_HCSR = 0x0e6C, /* 32 bit Host Control and Status Register */ -}; - /* ASF Subsystem Registers (Yukon-2 only) */ enum { B28_Y2_SMB_CONFIG = 0x0e40,/* 32 bit ASF SMBus Config Register */ @@ -853,27 +837,33 @@ enum { GMAC_LINK_CTRL = 0x0f10,/* 16 bit Link Control Reg */ /* Wake-up Frame Pattern Match Control Registers (YUKON only) */ + + WOL_REG_OFFS = 0x20,/* HW-Bug: Address is + 0x20 against spec. */ + WOL_CTRL_STAT = 0x0f20,/* 16 bit WOL Control/Status Reg */ WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */ WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */ WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */ + WOL_PATT_PME = 0x0f2a,/* 8 bit WOL PME Match Enable (Yukon-2) */ + WOL_PATT_ASFM = 0x0f2b,/* 8 bit WOL ASF Match Enable (Yukon-2) */ WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */ /* WOL Pattern Length Registers (YUKON only) */ + WOL_PATT_LEN_LO = 0x0f30,/* 32 bit WOL Pattern Length 3..0 */ WOL_PATT_LEN_HI = 0x0f34,/* 24 bit WOL Pattern Length 6..4 */ /* WOL Pattern Counter Registers (YUKON only) */ + + WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */ WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */ }; -#define WOL_REGS(port, x) (x + (port)*0x80) enum { WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */ WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */ }; -#define WOL_PATT_RAM_BASE(port) (WOL_PATT_RAM_1 + (port)*0x400) enum { BASE_GMAC_1 = 0x2800,/* GMAC 1 registers */ @@ -1664,39 +1654,6 @@ enum { Y2_ASF_CLR_ASFI = 1<<1, /* Clear host IRQ */ Y2_ASF_HOST_IRQ = 1<<0, /* Issue an IRQ to HOST system */ }; -/* HCU_CCSR CPU Control and Status Register */ -enum { - HCU_CCSR_SMBALERT_MONITOR= 1<<27, /* SMBALERT pin monitor */ - HCU_CCSR_CPU_SLEEP = 1<<26, /* CPU sleep status */ - /* Clock Stretching Timeout */ - HCU_CCSR_CS_TO = 1<<25, - HCU_CCSR_WDOG = 1<<24, /* Watchdog Reset */ - - HCU_CCSR_CLR_IRQ_HOST = 1<<17, /* Clear IRQ_HOST */ - HCU_CCSR_SET_IRQ_HCU = 1<<16, /* Set IRQ_HCU */ - - HCU_CCSR_AHB_RST = 1<<9, /* Reset AHB bridge */ - HCU_CCSR_CPU_RST_MODE = 1<<8, /* CPU Reset Mode */ - - HCU_CCSR_SET_SYNC_CPU = 1<<5, - HCU_CCSR_CPU_CLK_DIVIDE_MSK = 3<<3,/* CPU Clock Divide */ - HCU_CCSR_CPU_CLK_DIVIDE_BASE= 1<<3, - HCU_CCSR_OS_PRSNT = 1<<2, /* ASF OS Present */ -/* Microcontroller State */ - HCU_CCSR_UC_STATE_MSK = 3, - HCU_CCSR_UC_STATE_BASE = 1<<0, - HCU_CCSR_ASF_RESET = 0, - HCU_CCSR_ASF_HALTED = 1<<1, - HCU_CCSR_ASF_RUNNING = 1<<0, -}; - -/* HCU_HCSR Host Control and Status Register */ -enum { - HCU_HCSR_SET_IRQ_CPU = 1<<16, /* Set IRQ_CPU */ - - HCU_HCSR_CLR_IRQ_HCU = 1<<1, /* Clear IRQ_HCU */ - HCU_HCSR_SET_IRQ_HOST = 1<<0, /* Set IRQ_HOST */ -}; /* STAT_CTRL 32 bit Status BMU control register (Yukon-2 only) */ enum { @@ -1758,17 +1715,14 @@ enum { GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ #define GMAC_DEF_MSK GM_IS_TX_FF_UR -}; /* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ -enum { /* Bits 15.. 2: reserved */ + /* Bits 15.. 2: reserved */ GMLC_RST_CLR = 1<<1, /* Clear GMAC Link Reset */ GMLC_RST_SET = 1<<0, /* Set GMAC Link Reset */ -}; /* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ -enum { WOL_CTL_LINK_CHG_OCC = 1<<15, WOL_CTL_MAGIC_PKT_OCC = 1<<14, WOL_CTL_PATTERN_OCC = 1<<13, @@ -1787,6 +1741,17 @@ enum { WOL_CTL_DIS_PATTERN_UNIT = 1<<0, }; +#define WOL_CTL_DEFAULT \ + (WOL_CTL_DIS_PME_ON_LINK_CHG | \ + WOL_CTL_DIS_PME_ON_PATTERN | \ + WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ + WOL_CTL_DIS_LINK_CHG_UNIT | \ + WOL_CTL_DIS_PATTERN_UNIT | \ + WOL_CTL_DIS_MAGIC_PKT_UNIT) + +/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ +#define WOL_CTL_PATT_ENA(x) (1 << (x)) + /* Control flags */ enum { @@ -1910,7 +1875,6 @@ struct sky2_port { u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */ u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */ u8 rx_csum; - u8 wol; enum flow_control flow_mode; enum flow_control flow_status; @@ -1923,6 +1887,7 @@ struct sky2_hw { struct pci_dev *pdev; struct net_device *dev[2]; + int pm_cap; u8 chip_id; u8 chip_rev; u8 pmd_type; diff --git a/trunk/drivers/net/smc911x.c b/trunk/drivers/net/smc911x.c index c95614131980..43af61438449 100644 --- a/trunk/drivers/net/smc911x.c +++ b/trunk/drivers/net/smc911x.c @@ -1659,7 +1659,7 @@ smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strncpy(info->driver, CARDNAME, sizeof(info->driver)); strncpy(info->version, version, sizeof(info->version)); - strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); } static int smc911x_ethtool_nwayreset(struct net_device *dev) diff --git a/trunk/drivers/net/smc91x.c b/trunk/drivers/net/smc91x.c index 49f4b7712ebf..e62a9586fb95 100644 --- a/trunk/drivers/net/smc91x.c +++ b/trunk/drivers/net/smc91x.c @@ -1712,7 +1712,7 @@ smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strncpy(info->driver, CARDNAME, sizeof(info->driver)); strncpy(info->version, version, sizeof(info->version)); - strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); } static int smc_ethtool_nwayreset(struct net_device *dev) diff --git a/trunk/drivers/net/spider_net.c b/trunk/drivers/net/spider_net.c index bf6ff39e02bb..8ea2fc1b96cb 100644 --- a/trunk/drivers/net/spider_net.c +++ b/trunk/drivers/net/spider_net.c @@ -280,67 +280,72 @@ spider_net_free_chain(struct spider_net_card *card, { struct spider_net_descr *descr; - descr = chain->ring; - do { + for (descr = chain->tail; !descr->bus_addr; descr = descr->next) { + pci_unmap_single(card->pdev, descr->bus_addr, + SPIDER_NET_DESCR_SIZE, PCI_DMA_BIDIRECTIONAL); descr->bus_addr = 0; - descr->next_descr_addr = 0; - descr = descr->next; - } while (descr != chain->ring); - - dma_free_coherent(&card->pdev->dev, chain->num_desc, - chain->ring, chain->dma_addr); + } } /** - * spider_net_init_chain - alloc and link descriptor chain + * spider_net_init_chain - links descriptor chain * @card: card structure * @chain: address of chain + * @start_descr: address of descriptor array + * @no: number of descriptors * - * We manage a circular list that mirrors the hardware structure, + * we manage a circular list that mirrors the hardware structure, * except that the hardware uses bus addresses. * - * Returns 0 on success, <0 on failure + * returns 0 on success, <0 on failure */ static int spider_net_init_chain(struct spider_net_card *card, - struct spider_net_descr_chain *chain) + struct spider_net_descr_chain *chain, + struct spider_net_descr *start_descr, + int no) { int i; struct spider_net_descr *descr; dma_addr_t buf; - size_t alloc_size; - - alloc_size = chain->num_desc * sizeof (struct spider_net_descr); - chain->ring = dma_alloc_coherent(&card->pdev->dev, alloc_size, - &chain->dma_addr, GFP_KERNEL); + descr = start_descr; + memset(descr, 0, sizeof(*descr) * no); - if (!chain->ring) - return -ENOMEM; + /* set up the hardware pointers in each descriptor */ + for (i=0; idmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; - descr = chain->ring; - memset(descr, 0, alloc_size); + buf = pci_map_single(card->pdev, descr, + SPIDER_NET_DESCR_SIZE, + PCI_DMA_BIDIRECTIONAL); - /* Set up the hardware pointers in each descriptor */ - buf = chain->dma_addr; - for (i=0; i < chain->num_desc; i++, descr++) { - descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; + if (pci_dma_mapping_error(buf)) + goto iommu_error; descr->bus_addr = buf; - descr->next_descr_addr = 0; descr->next = descr + 1; descr->prev = descr - 1; - buf += sizeof(struct spider_net_descr); } /* do actual circular list */ - (descr-1)->next = chain->ring; - chain->ring->prev = descr-1; + (descr-1)->next = start_descr; + start_descr->prev = descr-1; spin_lock_init(&chain->lock); - chain->head = chain->ring; - chain->tail = chain->ring; + chain->head = start_descr; + chain->tail = start_descr; + return 0; + +iommu_error: + descr = start_descr; + for (i=0; i < no; i++, descr++) + if (descr->bus_addr) + pci_unmap_single(card->pdev, descr->bus_addr, + SPIDER_NET_DESCR_SIZE, + PCI_DMA_BIDIRECTIONAL); + return -ENOMEM; } /** @@ -367,20 +372,21 @@ spider_net_free_rx_chain_contents(struct spider_net_card *card) } /** - * spider_net_prepare_rx_descr - Reinitialize RX descriptor + * spider_net_prepare_rx_descr - reinitializes a rx descriptor * @card: card structure * @descr: descriptor to re-init * - * Return 0 on succes, <0 on failure. + * return 0 on succes, <0 on failure * - * Allocates a new rx skb, iommu-maps it and attaches it to the - * descriptor. Mark the descriptor as activated, ready-to-use. + * allocates a new rx skb, iommu-maps it and attaches it to the descriptor. + * Activate the descriptor state-wise */ static int spider_net_prepare_rx_descr(struct spider_net_card *card, struct spider_net_descr *descr) { dma_addr_t buf; + int error = 0; int offset; int bufsize; @@ -408,7 +414,7 @@ spider_net_prepare_rx_descr(struct spider_net_card *card, (SPIDER_NET_RXBUF_ALIGN - 1); if (offset) skb_reserve(descr->skb, SPIDER_NET_RXBUF_ALIGN - offset); - /* iommu-map the skb */ + /* io-mmu-map the skb */ buf = pci_map_single(card->pdev, descr->skb->data, SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE); descr->buf_addr = buf; @@ -419,16 +425,11 @@ spider_net_prepare_rx_descr(struct spider_net_card *card, card->spider_stats.rx_iommu_map_error++; descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; } else { - descr->next_descr_addr = 0; - wmb(); descr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOINTR_COMPLETE; - - wmb(); - descr->prev->next_descr_addr = descr->bus_addr; } - return 0; + return error; } /** @@ -492,10 +493,10 @@ spider_net_refill_rx_chain(struct spider_net_card *card) } /** - * spider_net_alloc_rx_skbs - Allocates rx skbs in rx descriptor chains + * spider_net_alloc_rx_skbs - allocates rx skbs in rx descriptor chains * @card: card structure * - * Returns 0 on success, <0 on failure. + * returns 0 on success, <0 on failure */ static int spider_net_alloc_rx_skbs(struct spider_net_card *card) @@ -506,16 +507,16 @@ spider_net_alloc_rx_skbs(struct spider_net_card *card) result = -ENOMEM; chain = &card->rx_chain; - /* Put at least one buffer into the chain. if this fails, - * we've got a problem. If not, spider_net_refill_rx_chain - * will do the rest at the end of this function. */ + /* put at least one buffer into the chain. if this fails, + * we've got a problem. if not, spider_net_refill_rx_chain + * will do the rest at the end of this function */ if (spider_net_prepare_rx_descr(card, chain->head)) goto error; else chain->head = chain->head->next; - /* This will allocate the rest of the rx buffers; - * if not, it's business as usual later on. */ + /* this will allocate the rest of the rx buffers; if not, it's + * business as usual later on */ spider_net_refill_rx_chain(card); spider_net_enable_rxdmac(card); return 0; @@ -706,7 +707,7 @@ spider_net_set_low_watermark(struct spider_net_card *card) } /* If TX queue is short, don't even bother with interrupts */ - if (cnt < card->tx_chain.num_desc/4) + if (cnt < card->num_tx_desc/4) return cnt; /* Set low-watermark 3/4th's of the way into the queue. */ @@ -914,13 +915,16 @@ spider_net_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) * spider_net_pass_skb_up - takes an skb from a descriptor and passes it on * @descr: descriptor to process * @card: card structure + * @napi: whether caller is in NAPI context + * + * returns 1 on success, 0 if no packet was passed to the stack * - * Fills out skb structure and passes the data to the stack. - * The descriptor state is not changed. + * iommu-unmaps the skb, fills out skb structure and passes the data to the + * stack. The descriptor state is not changed. */ -static void +static int spider_net_pass_skb_up(struct spider_net_descr *descr, - struct spider_net_card *card) + struct spider_net_card *card, int napi) { struct sk_buff *skb; struct net_device *netdev; @@ -928,8 +932,23 @@ spider_net_pass_skb_up(struct spider_net_descr *descr, data_status = descr->data_status; data_error = descr->data_error; + netdev = card->netdev; + /* unmap descriptor */ + pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_FRAME, + PCI_DMA_FROMDEVICE); + + /* the cases we'll throw away the packet immediately */ + if (data_error & SPIDER_NET_DESTROY_RX_FLAGS) { + if (netif_msg_rx_err(card)) + pr_err("error in received descriptor found, " + "data_status=x%08x, data_error=x%08x\n", + data_status, data_error); + card->spider_stats.rx_desc_error++; + return 0; + } + skb = descr->skb; skb->dev = netdev; skb_put(skb, descr->valid_size); @@ -958,72 +977,57 @@ spider_net_pass_skb_up(struct spider_net_descr *descr, } /* pass skb up to stack */ - netif_receive_skb(skb); + if (napi) + netif_receive_skb(skb); + else + netif_rx_ni(skb); /* update netdevice statistics */ card->netdev_stats.rx_packets++; card->netdev_stats.rx_bytes += skb->len; -} - -#ifdef DEBUG -static void show_rx_chain(struct spider_net_card *card) -{ - struct spider_net_descr_chain *chain = &card->rx_chain; - struct spider_net_descr *start= chain->tail; - struct spider_net_descr *descr= start; - int status; - int cnt = 0; - int cstat = spider_net_get_descr_status(descr); - printk(KERN_INFO "RX chain tail at descr=%ld\n", - (start - card->descr) - card->tx_chain.num_desc); - status = cstat; - do - { - status = spider_net_get_descr_status(descr); - if (cstat != status) { - printk(KERN_INFO "Have %d descrs with stat=x%08x\n", cnt, cstat); - cstat = status; - cnt = 0; - } - cnt ++; - descr = descr->next; - } while (descr != start); - printk(KERN_INFO "Last %d descrs with stat=x%08x\n", cnt, cstat); + return 1; } -#endif /** * spider_net_decode_one_descr - processes an rx descriptor * @card: card structure + * @napi: whether caller is in NAPI context * - * Returns 1 if a packet has been sent to the stack, otherwise 0 + * returns 1 if a packet has been sent to the stack, otherwise 0 * - * Processes an rx descriptor by iommu-unmapping the data buffer and passing + * processes an rx descriptor by iommu-unmapping the data buffer and passing * the packet up to the stack. This function is called in softirq * context, e.g. either bottom half from interrupt or NAPI polling context */ static int -spider_net_decode_one_descr(struct spider_net_card *card) +spider_net_decode_one_descr(struct spider_net_card *card, int napi) { struct spider_net_descr_chain *chain = &card->rx_chain; struct spider_net_descr *descr = chain->tail; int status; + int result; status = spider_net_get_descr_status(descr); - /* Nothing in the descriptor, or ring must be empty */ - if ((status == SPIDER_NET_DESCR_CARDOWNED) || - (status == SPIDER_NET_DESCR_NOT_IN_USE)) - return 0; + if (status == SPIDER_NET_DESCR_CARDOWNED) { + /* nothing in the descriptor yet */ + result=0; + goto out; + } + + if (status == SPIDER_NET_DESCR_NOT_IN_USE) { + /* not initialized yet, the ring must be empty */ + spider_net_refill_rx_chain(card); + spider_net_enable_rxdmac(card); + result=0; + goto out; + } /* descriptor definitively used -- move on tail */ chain->tail = descr->next; - /* unmap descriptor */ - pci_unmap_single(card->pdev, descr->buf_addr, - SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE); - + result = 0; if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) || (status == SPIDER_NET_DESCR_PROTECTION_ERROR) || (status == SPIDER_NET_DESCR_FORCE_END) ) { @@ -1031,55 +1035,31 @@ spider_net_decode_one_descr(struct spider_net_card *card) pr_err("%s: dropping RX descriptor with state %d\n", card->netdev->name, status); card->netdev_stats.rx_dropped++; - goto bad_desc; + pci_unmap_single(card->pdev, descr->buf_addr, + SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE); + dev_kfree_skb_irq(descr->skb); + goto refill; } if ( (status != SPIDER_NET_DESCR_COMPLETE) && (status != SPIDER_NET_DESCR_FRAME_END) ) { - if (netif_msg_rx_err(card)) - pr_err("%s: RX descriptor with unkown state %d\n", + if (netif_msg_rx_err(card)) { + pr_err("%s: RX descriptor with state %d\n", card->netdev->name, status); - card->spider_stats.rx_desc_unk_state++; - goto bad_desc; - } - - /* The cases we'll throw away the packet immediately */ - if (descr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) { - if (netif_msg_rx_err(card)) - pr_err("%s: error in received descriptor found, " - "data_status=x%08x, data_error=x%08x\n", - card->netdev->name, - descr->data_status, descr->data_error); - goto bad_desc; - } - - if (descr->dmac_cmd_status & 0xfefe) { - pr_err("%s: bad status, cmd_status=x%08x\n", - card->netdev->name, - descr->dmac_cmd_status); - pr_err("buf_addr=x%08x\n", descr->buf_addr); - pr_err("buf_size=x%08x\n", descr->buf_size); - pr_err("next_descr_addr=x%08x\n", descr->next_descr_addr); - pr_err("result_size=x%08x\n", descr->result_size); - pr_err("valid_size=x%08x\n", descr->valid_size); - pr_err("data_status=x%08x\n", descr->data_status); - pr_err("data_error=x%08x\n", descr->data_error); - pr_err("bus_addr=x%08x\n", descr->bus_addr); - pr_err("which=%ld\n", descr - card->rx_chain.ring); - - card->spider_stats.rx_desc_error++; - goto bad_desc; + card->spider_stats.rx_desc_unk_state++; + } + goto refill; } - /* Ok, we've got a packet in descr */ - spider_net_pass_skb_up(descr, card); + /* ok, we've got a packet in descr */ + result = spider_net_pass_skb_up(descr, card, napi); +refill: descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; - return 1; - -bad_desc: - dev_kfree_skb_irq(descr->skb); - descr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE; - return 0; + /* change the descriptor state: */ + if (!napi) + spider_net_refill_rx_chain(card); +out: + return result; } /** @@ -1105,7 +1085,7 @@ spider_net_poll(struct net_device *netdev, int *budget) packets_to_do = min(*budget, netdev->quota); while (packets_to_do) { - if (spider_net_decode_one_descr(card)) { + if (spider_net_decode_one_descr(card, 1)) { packets_done++; packets_to_do--; } else { @@ -1118,7 +1098,6 @@ spider_net_poll(struct net_device *netdev, int *budget) netdev->quota -= packets_done; *budget -= packets_done; spider_net_refill_rx_chain(card); - spider_net_enable_rxdmac(card); /* if all packets are in the stack, enable interrupts and return 0 */ /* if not, return 1 */ @@ -1247,6 +1226,24 @@ spider_net_set_mac(struct net_device *netdev, void *p) return 0; } +/** + * spider_net_handle_rxram_full - cleans up RX ring upon RX RAM full interrupt + * @card: card structure + * + * spider_net_handle_rxram_full empties the RX ring so that spider can put + * more packets in it and empty its RX RAM. This is called in bottom half + * context + */ +static void +spider_net_handle_rxram_full(struct spider_net_card *card) +{ + while (spider_net_decode_one_descr(card, 0)) + ; + spider_net_enable_rxchtails(card); + spider_net_enable_rxdmac(card); + netif_rx_schedule(card->netdev); +} + /** * spider_net_handle_error_irq - handles errors raised by an interrupt * @card: card structure @@ -1369,10 +1366,10 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) case SPIDER_NET_GRFAFLLINT: /* fallthrough */ case SPIDER_NET_GRMFLLINT: if (netif_msg_intr(card) && net_ratelimit()) - pr_err("Spider RX RAM full, incoming packets " + pr_debug("Spider RX RAM full, incoming packets " "might be discarded!\n"); spider_net_rx_irq_off(card); - netif_rx_schedule(card->netdev); + tasklet_schedule(&card->rxram_full_tl); show_error = 0; break; @@ -1387,7 +1384,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) case SPIDER_NET_GDCDCEINT: /* fallthrough */ case SPIDER_NET_GDBDCEINT: /* fallthrough */ case SPIDER_NET_GDADCEINT: - if (netif_msg_intr(card) && net_ratelimit()) + if (netif_msg_intr(card)) pr_err("got descriptor chain end interrupt, " "restarting DMAC %c.\n", 'D'-(i-SPIDER_NET_GDDDCEINT)/3); @@ -1458,7 +1455,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) break; } - if ((show_error) && (netif_msg_intr(card)) && net_ratelimit()) + if ((show_error) && (netif_msg_intr(card))) pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, " "GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n", card->netdev->name, @@ -1654,18 +1651,27 @@ int spider_net_open(struct net_device *netdev) { struct spider_net_card *card = netdev_priv(netdev); - int result; + struct spider_net_descr *descr; + int i, result; - result = spider_net_init_chain(card, &card->tx_chain); - if (result) + result = -ENOMEM; + if (spider_net_init_chain(card, &card->tx_chain, card->descr, + card->num_tx_desc)) goto alloc_tx_failed; + card->low_watermark = NULL; - result = spider_net_init_chain(card, &card->rx_chain); - if (result) + /* rx_chain is after tx_chain, so offset is descr + tx_count */ + if (spider_net_init_chain(card, &card->rx_chain, + card->descr + card->num_tx_desc, + card->num_rx_desc)) goto alloc_rx_failed; - /* Allocate rx skbs */ + descr = card->rx_chain.head; + for (i=0; i < card->num_rx_desc; i++, descr++) + descr->next_descr_addr = descr->next->bus_addr; + + /* allocate rx skbs */ if (spider_net_alloc_rx_skbs(card)) goto alloc_skbs_failed; @@ -1896,6 +1902,7 @@ spider_net_stop(struct net_device *netdev) { struct spider_net_card *card = netdev_priv(netdev); + tasklet_kill(&card->rxram_full_tl); netif_poll_disable(netdev); netif_carrier_off(netdev); netif_stop_queue(netdev); @@ -1917,7 +1924,6 @@ spider_net_stop(struct net_device *netdev) /* release chains */ spider_net_release_tx_chain(card, 1); - spider_net_free_rx_chain_contents(card); spider_net_free_rx_chain_contents(card); @@ -2040,6 +2046,9 @@ spider_net_setup_netdev(struct spider_net_card *card) pci_set_drvdata(card->pdev, netdev); + card->rxram_full_tl.data = (unsigned long) card; + card->rxram_full_tl.func = + (void (*)(unsigned long)) spider_net_handle_rxram_full; init_timer(&card->tx_timer); card->tx_timer.function = (void (*)(unsigned long)) spider_net_cleanup_tx_ring; @@ -2048,8 +2057,8 @@ spider_net_setup_netdev(struct spider_net_card *card) card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT; - card->tx_chain.num_desc = tx_descriptors; - card->rx_chain.num_desc = rx_descriptors; + card->num_tx_desc = tx_descriptors; + card->num_rx_desc = rx_descriptors; spider_net_setup_netdev_ops(netdev); @@ -2098,8 +2107,12 @@ spider_net_alloc_card(void) { struct net_device *netdev; struct spider_net_card *card; + size_t alloc_size; - netdev = alloc_etherdev(sizeof(struct spider_net_card)); + alloc_size = sizeof (*card) + + sizeof (struct spider_net_descr) * rx_descriptors + + sizeof (struct spider_net_descr) * tx_descriptors; + netdev = alloc_etherdev(alloc_size); if (!netdev) return NULL; diff --git a/trunk/drivers/net/spider_net.h b/trunk/drivers/net/spider_net.h index 2fec5cf76926..3e196df29790 100644 --- a/trunk/drivers/net/spider_net.h +++ b/trunk/drivers/net/spider_net.h @@ -24,7 +24,7 @@ #ifndef _SPIDER_NET_H #define _SPIDER_NET_H -#define VERSION "1.6 B" +#define VERSION "1.6 A" #include "sungem_phy.h" @@ -378,9 +378,6 @@ struct spider_net_descr_chain { spinlock_t lock; struct spider_net_descr *head; struct spider_net_descr *tail; - struct spider_net_descr *ring; - int num_desc; - dma_addr_t dma_addr; }; /* descriptor data_status bits */ @@ -400,6 +397,8 @@ struct spider_net_descr_chain { * 701b8000 would be correct, but every packets gets that flag */ #define SPIDER_NET_DESTROY_RX_FLAGS 0x700b8000 +#define SPIDER_NET_DESCR_SIZE 32 + /* this will be bigger some time */ struct spider_net_options { int rx_csum; /* for rx: if 0 ip_summed=NONE, @@ -442,16 +441,25 @@ struct spider_net_card { struct spider_net_descr_chain rx_chain; struct spider_net_descr *low_watermark; + struct net_device_stats netdev_stats; + + struct spider_net_options options; + + spinlock_t intmask_lock; + struct tasklet_struct rxram_full_tl; struct timer_list tx_timer; + struct work_struct tx_timeout_task; atomic_t tx_timeout_task_counter; wait_queue_head_t waitq; /* for ethtool */ int msg_enable; - struct net_device_stats netdev_stats; + int num_rx_desc; + int num_tx_desc; struct spider_net_extra_stats spider_stats; - struct spider_net_options options; + + struct spider_net_descr descr[0]; }; #define pr_err(fmt,arg...) \ diff --git a/trunk/drivers/net/spider_net_ethtool.c b/trunk/drivers/net/spider_net_ethtool.c index 6bcf03fc89be..91b995102915 100644 --- a/trunk/drivers/net/spider_net_ethtool.c +++ b/trunk/drivers/net/spider_net_ethtool.c @@ -158,9 +158,9 @@ spider_net_ethtool_get_ringparam(struct net_device *netdev, struct spider_net_card *card = netdev->priv; ering->tx_max_pending = SPIDER_NET_TX_DESCRIPTORS_MAX; - ering->tx_pending = card->tx_chain.num_desc; + ering->tx_pending = card->num_tx_desc; ering->rx_max_pending = SPIDER_NET_RX_DESCRIPTORS_MAX; - ering->rx_pending = card->rx_chain.num_desc; + ering->rx_pending = card->num_rx_desc; } static int spider_net_get_stats_count(struct net_device *netdev) diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 135c0987deae..f4bf62c2a7a5 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -58,7 +58,11 @@ #define TG3_VLAN_TAG_USED 0 #endif +#ifdef NETIF_F_TSO #define TG3_TSO_SUPPORT 1 +#else +#define TG3_TSO_SUPPORT 0 +#endif #include "tg3.h" @@ -3869,6 +3873,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) entry = tp->tx_prod; base_flags = 0; +#if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && (mss = skb_shinfo(skb)->gso_size) != 0) { @@ -3901,6 +3906,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) } else if (skb->ip_summed == CHECKSUM_PARTIAL) base_flags |= TXD_FLAG_TCPUDP_CSUM; +#else + mss = 0; + if (skb->ip_summed == CHECKSUM_PARTIAL) + base_flags |= TXD_FLAG_TCPUDP_CSUM; +#endif #if TG3_VLAN_TAG_USED if (tp->vlgrp != NULL && vlan_tx_tag_present(skb)) base_flags |= (TXD_FLAG_VLAN | @@ -3960,6 +3970,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +#if TG3_TSO_SUPPORT != 0 static int tg3_start_xmit_dma_bug(struct sk_buff *, struct net_device *); /* Use GSO to workaround a rare TSO bug that may be triggered when the @@ -3991,6 +4002,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) return NETDEV_TX_OK; } +#endif /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and * support TG3_FLG2_HW_TSO_1 or firmware TSO only. @@ -4024,6 +4036,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) base_flags = 0; if (skb->ip_summed == CHECKSUM_PARTIAL) base_flags |= TXD_FLAG_TCPUDP_CSUM; +#if TG3_TSO_SUPPORT != 0 mss = 0; if (skb->len > (tp->dev->mtu + ETH_HLEN) && (mss = skb_shinfo(skb)->gso_size) != 0) { @@ -4078,6 +4091,9 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) } } } +#else + mss = 0; +#endif #if TG3_VLAN_TAG_USED if (tp->vlgrp != NULL && vlan_tx_tag_present(skb)) base_flags |= (TXD_FLAG_VLAN | @@ -5313,6 +5329,7 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) return 0; } +#if TG3_TSO_SUPPORT != 0 #define TG3_TSO_FW_RELEASE_MAJOR 0x1 #define TG3_TSO_FW_RELASE_MINOR 0x6 @@ -5889,6 +5906,7 @@ static int tg3_load_tso_firmware(struct tg3 *tp) return 0; } +#endif /* TG3_TSO_SUPPORT != 0 */ /* tp->lock is held. */ static void __tg3_set_mac_addr(struct tg3 *tp) @@ -6102,6 +6120,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE); tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE); } +#if TG3_TSO_SUPPORT != 0 else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { int fw_len; @@ -6116,6 +6135,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE5705 - fw_len - 0xa00); } +#endif if (tp->dev->mtu <= ETH_DATA_LEN) { tw32(BUFMGR_MB_RDMA_LOW_WATER, @@ -6317,8 +6337,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; +#if TG3_TSO_SUPPORT != 0 if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) rdmac_mode |= (1 << 27); +#endif /* Receive/send statistics. */ if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) { @@ -6489,8 +6511,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB); tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ); tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); +#if TG3_TSO_SUPPORT != 0 if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8); +#endif tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE); tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE); @@ -6500,11 +6524,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) return err; } +#if TG3_TSO_SUPPORT != 0 if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { err = tg3_load_tso_firmware(tp); if (err) return err; } +#endif tp->tx_mode = TX_MODE_ENABLE; tw32_f(MAC_TX_MODE, tp->tx_mode); @@ -8036,6 +8062,7 @@ static void tg3_set_msglevel(struct net_device *dev, u32 value) tp->msg_enable = value; } +#if TG3_TSO_SUPPORT != 0 static int tg3_set_tso(struct net_device *dev, u32 value) { struct tg3 *tp = netdev_priv(dev); @@ -8054,6 +8081,7 @@ static int tg3_set_tso(struct net_device *dev, u32 value) } return ethtool_op_set_tso(dev, value); } +#endif static int tg3_nway_reset(struct net_device *dev) { @@ -9184,8 +9212,10 @@ static const struct ethtool_ops tg3_ethtool_ops = { .set_tx_csum = tg3_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, +#if TG3_TSO_SUPPORT != 0 .get_tso = ethtool_op_get_tso, .set_tso = tg3_set_tso, +#endif .self_test_count = tg3_get_test_count, .self_test = tg3_self_test, .get_strings = tg3_get_strings, @@ -11826,6 +11856,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_bufmgr_config(tp); +#if TG3_TSO_SUPPORT != 0 if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; } @@ -11850,6 +11881,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, dev->features |= NETIF_F_TSO6; } +#endif if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && diff --git a/trunk/drivers/net/ucc_geth.c b/trunk/drivers/net/ucc_geth.c index abb8611c5a91..7e4b23c7c1ba 100644 --- a/trunk/drivers/net/ucc_geth.c +++ b/trunk/drivers/net/ucc_geth.c @@ -2865,8 +2865,8 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4) align = UCC_GETH_TX_BD_RING_ALIGNMENT; ugeth->tx_bd_ring_offset[j] = - kmalloc((u32) (length + align), GFP_KERNEL); - + (u32) (kmalloc((u32) (length + align), + GFP_KERNEL)); if (ugeth->tx_bd_ring_offset[j] != 0) ugeth->p_tx_bd_ring[j] = (void*)((ugeth->tx_bd_ring_offset[j] + @@ -2901,7 +2901,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4) align = UCC_GETH_RX_BD_RING_ALIGNMENT; ugeth->rx_bd_ring_offset[j] = - kmalloc((u32) (length + align), GFP_KERNEL); + (u32) (kmalloc((u32) (length + align), GFP_KERNEL)); if (ugeth->rx_bd_ring_offset[j] != 0) ugeth->p_rx_bd_ring[j] = (void*)((ugeth->rx_bd_ring_offset[j] + @@ -2927,9 +2927,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* Init Tx bds */ for (j = 0; j < ug_info->numQueuesTx; j++) { /* Setup the skbuff rings */ - ugeth->tx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) * - ugeth->ug_info->bdRingLenTx[j], - GFP_KERNEL); + ugeth->tx_skbuff[j] = + (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) * + ugeth->ug_info->bdRingLenTx[j], + GFP_KERNEL); if (ugeth->tx_skbuff[j] == NULL) { ugeth_err("%s: Could not allocate tx_skbuff", @@ -2958,9 +2959,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) /* Init Rx bds */ for (j = 0; j < ug_info->numQueuesRx; j++) { /* Setup the skbuff rings */ - ugeth->rx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) * - ugeth->ug_info->bdRingLenRx[j], - GFP_KERNEL); + ugeth->rx_skbuff[j] = + (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) * + ugeth->ug_info->bdRingLenRx[j], + GFP_KERNEL); if (ugeth->rx_skbuff[j] == NULL) { ugeth_err("%s: Could not allocate rx_skbuff", @@ -3451,7 +3453,8 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth) * allocated resources can be released when the channel is freed. */ if (!(ugeth->p_init_enet_param_shadow = - kmalloc(sizeof(struct ucc_geth_init_pram), GFP_KERNEL))) { + (struct ucc_geth_init_pram *) kmalloc(sizeof(struct ucc_geth_init_pram), + GFP_KERNEL))) { ugeth_err ("%s: Can not allocate memory for" " p_UccInitEnetParamShadows.", __FUNCTION__); diff --git a/trunk/drivers/net/wan/Kconfig b/trunk/drivers/net/wan/Kconfig index 61708cf4c85d..21f76f51c95e 100644 --- a/trunk/drivers/net/wan/Kconfig +++ b/trunk/drivers/net/wan/Kconfig @@ -235,19 +235,6 @@ comment "Cyclades-PC300 MLPPP support is disabled." comment "Refer to the file README.mlppp, provided by PC300 package." depends on WAN && HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP) -config PC300TOO - tristate "Cyclades PC300 RSV/X21 alternative support" - depends on HDLC && PCI - help - Alternative driver for PC300 RSV/X21 PCI cards made by - Cyclades, Inc. If you have such a card, say Y here and see - . - - To compile this as a module, choose M here: the module - will be called pc300too. - - If unsure, say N here. - config N2 tristate "SDL RISCom/N2 support" depends on HDLC && ISA @@ -357,6 +344,17 @@ config DLCI To compile this driver as a module, choose M here: the module will be called dlci. +config DLCI_COUNT + int "Max open DLCI" + depends on DLCI + default "24" + help + Maximal number of logical point-to-point frame relay connections + (the identifiers of which are called DCLIs) that the driver can + handle. + + The default is probably fine. + config DLCI_MAX int "Max DLCI per device" depends on DLCI diff --git a/trunk/drivers/net/wan/Makefile b/trunk/drivers/net/wan/Makefile index d61fef36afc9..83ec2c87ba3f 100644 --- a/trunk/drivers/net/wan/Makefile +++ b/trunk/drivers/net/wan/Makefile @@ -41,7 +41,6 @@ obj-$(CONFIG_N2) += n2.o obj-$(CONFIG_C101) += c101.o obj-$(CONFIG_WANXL) += wanxl.o obj-$(CONFIG_PCI200SYN) += pci200syn.o -obj-$(CONFIG_PC300TOO) += pc300too.o clean-files := wanxlfw.inc $(obj)/wanxl.o: $(obj)/wanxlfw.inc diff --git a/trunk/drivers/net/wan/hdlc.c b/trunk/drivers/net/wan/hdlc.c index 9040d7cf651e..db354e0edbe5 100644 --- a/trunk/drivers/net/wan/hdlc.c +++ b/trunk/drivers/net/wan/hdlc.c @@ -222,7 +222,7 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EINVAL; } -static void hdlc_setup(struct net_device *dev) +void hdlc_setup(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); @@ -325,6 +325,7 @@ MODULE_LICENSE("GPL v2"); EXPORT_SYMBOL(hdlc_open); EXPORT_SYMBOL(hdlc_close); EXPORT_SYMBOL(hdlc_ioctl); +EXPORT_SYMBOL(hdlc_setup); EXPORT_SYMBOL(alloc_hdlcdev); EXPORT_SYMBOL(unregister_hdlc_device); EXPORT_SYMBOL(register_hdlc_protocol); diff --git a/trunk/drivers/net/wan/pc300too.c b/trunk/drivers/net/wan/pc300too.c deleted file mode 100644 index 79b2d5454d6b..000000000000 --- a/trunk/drivers/net/wan/pc300too.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Cyclades PC300 synchronous serial card driver for Linux - * - * Copyright (C) 2000-2007 Krzysztof Halasa - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * For information see . - * - * Sources of information: - * Hitachi HD64572 SCA-II User's Manual - * Cyclades PC300 Linux driver - * - * This driver currently supports only PC300/RSV (V.24/V.35) and - * PC300/X21 cards. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hd64572.h" - -static const char* version = "Cyclades PC300 driver version: 1.17"; -static const char* devname = "PC300"; - -#undef DEBUG_PKT -#define DEBUG_RINGS - -#define PC300_PLX_SIZE 0x80 /* PLX control window size (128 B) */ -#define PC300_SCA_SIZE 0x400 /* SCA window size (1 KB) */ -#define ALL_PAGES_ALWAYS_MAPPED -#define NEED_DETECT_RAM -#define NEED_SCA_MSCI_INTR -#define MAX_TX_BUFFERS 10 - -static int pci_clock_freq = 33000000; -static int use_crystal_clock = 0; -static unsigned int CLOCK_BASE; - -/* Masks to access the init_ctrl PLX register */ -#define PC300_CLKSEL_MASK (0x00000004UL) -#define PC300_CHMEDIA_MASK(port) (0x00000020UL << ((port) * 3)) -#define PC300_CTYPE_MASK (0x00000800UL) - - -enum { PC300_RSV = 1, PC300_X21, PC300_TE }; /* card types */ - -/* - * PLX PCI9050-1 local configuration and shared runtime registers. - * This structure can be used to access 9050 registers (memory mapped). - */ -typedef struct { - u32 loc_addr_range[4]; /* 00-0Ch : Local Address Ranges */ - u32 loc_rom_range; /* 10h : Local ROM Range */ - u32 loc_addr_base[4]; /* 14-20h : Local Address Base Addrs */ - u32 loc_rom_base; /* 24h : Local ROM Base */ - u32 loc_bus_descr[4]; /* 28-34h : Local Bus Descriptors */ - u32 rom_bus_descr; /* 38h : ROM Bus Descriptor */ - u32 cs_base[4]; /* 3C-48h : Chip Select Base Addrs */ - u32 intr_ctrl_stat; /* 4Ch : Interrupt Control/Status */ - u32 init_ctrl; /* 50h : EEPROM ctrl, Init Ctrl, etc */ -}plx9050; - - - -typedef struct port_s { - struct net_device *dev; - struct card_s *card; - spinlock_t lock; /* TX lock */ - sync_serial_settings settings; - int rxpart; /* partial frame received, next frame invalid*/ - unsigned short encoding; - unsigned short parity; - unsigned int iface; - u16 rxin; /* rx ring buffer 'in' pointer */ - u16 txin; /* tx ring buffer 'in' and 'last' pointers */ - u16 txlast; - u8 rxs, txs, tmc; /* SCA registers */ - u8 phy_node; /* physical port # - 0 or 1 */ -}port_t; - - - -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) */ - 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 */ - u16 tx_ring_buffers; - u16 buff_offset; /* offset of first buffer of first channel */ - u8 irq; /* interrupt request level */ - - port_t ports[2]; -}card_t; - - -#define sca_in(reg, card) readb(card->scabase + (reg)) -#define sca_out(value, reg, card) writeb(value, card->scabase + (reg)) -#define sca_inw(reg, card) readw(card->scabase + (reg)) -#define sca_outw(value, reg, card) writew(value, card->scabase + (reg)) -#define sca_inl(reg, card) readl(card->scabase + (reg)) -#define sca_outl(value, reg, card) writel(value, card->scabase + (reg)) - -#define port_to_card(port) (port->card) -#define log_node(port) (port->phy_node) -#define phy_node(port) (port->phy_node) -#define winbase(card) (card->rambase) -#define get_port(card, port) ((port) < (card)->n_ports ? \ - (&(card)->ports[port]) : (NULL)) - -#include "hd6457x.c" - - -static void pc300_set_iface(port_t *port) -{ - card_t *card = port->card; - u32* 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; - - sca_out(EXS_TES1, (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS, - port_to_card(port)); - switch(port->settings.clock_type) { - case CLOCK_INT: - rxs |= CLK_BRG; /* BRG output */ - txs |= CLK_PIN_OUT | CLK_TX_RXCLK; /* RX clock */ - break; - - case CLOCK_TXINT: - rxs |= CLK_LINE; /* RXC input */ - txs |= CLK_PIN_OUT | CLK_BRG; /* BRG output */ - break; - - case CLOCK_TXFROMRX: - rxs |= CLK_LINE; /* RXC input */ - txs |= CLK_PIN_OUT | CLK_TX_RXCLK; /* RX clock */ - break; - - default: /* EXTernal clock */ - rxs |= CLK_LINE; /* RXC input */ - txs |= CLK_PIN_OUT | CLK_LINE; /* TXC input */ - break; - } - - port->rxs = rxs; - port->txs = txs; - sca_out(rxs, msci + RXS, card); - sca_out(txs, msci + TXS, card); - sca_set_port(port); - - if (port->card->type == PC300_RSV) { - if (port->iface == IF_IFACE_V35) - writel(card->init_ctrl_value | - PC300_CHMEDIA_MASK(port->phy_node), init_ctrl); - else - writel(card->init_ctrl_value & - ~PC300_CHMEDIA_MASK(port->phy_node), init_ctrl); - } -} - - - -static int pc300_open(struct net_device *dev) -{ - port_t *port = dev_to_port(dev); - - int result = hdlc_open(dev); - if (result) - return result; - - sca_open(dev); - pc300_set_iface(port); - return 0; -} - - - -static int pc300_close(struct net_device *dev) -{ - sca_close(dev); - hdlc_close(dev); - return 0; -} - - - -static int pc300_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - const size_t size = sizeof(sync_serial_settings); - sync_serial_settings new_line; - sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; - int new_type; - port_t *port = dev_to_port(dev); - -#ifdef DEBUG_RINGS - if (cmd == SIOCDEVPRIVATE) { - sca_dump_rings(dev); - return 0; - } -#endif - if (cmd != SIOCWANDEV) - return hdlc_ioctl(dev, ifr, cmd); - - if (ifr->ifr_settings.type == IF_GET_IFACE) { - ifr->ifr_settings.type = port->iface; - if (ifr->ifr_settings.size < size) { - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } - if (copy_to_user(line, &port->settings, size)) - return -EFAULT; - return 0; - - } - - if (port->card->type == PC300_X21 && - (ifr->ifr_settings.type == IF_IFACE_SYNC_SERIAL || - ifr->ifr_settings.type == IF_IFACE_X21)) - new_type = IF_IFACE_X21; - - else if (port->card->type == PC300_RSV && - (ifr->ifr_settings.type == IF_IFACE_SYNC_SERIAL || - ifr->ifr_settings.type == IF_IFACE_V35)) - new_type = IF_IFACE_V35; - - else if (port->card->type == PC300_RSV && - ifr->ifr_settings.type == IF_IFACE_V24) - new_type = IF_IFACE_V24; - - else - return hdlc_ioctl(dev, ifr, cmd); - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (copy_from_user(&new_line, line, size)) - return -EFAULT; - - if (new_line.clock_type != CLOCK_EXT && - new_line.clock_type != CLOCK_TXFROMRX && - new_line.clock_type != CLOCK_INT && - new_line.clock_type != CLOCK_TXINT) - return -EINVAL; /* No such clock setting */ - - if (new_line.loopback != 0 && new_line.loopback != 1) - return -EINVAL; - - memcpy(&port->settings, &new_line, size); /* Update settings */ - port->iface = new_type; - pc300_set_iface(port); - return 0; -} - - - -static void pc300_pci_remove_one(struct pci_dev *pdev) -{ - int i; - card_t *card = pci_get_drvdata(pdev); - - for (i = 0; i < 2; i++) - if (card->ports[i].card) { - struct net_device *dev = port_to_dev(&card->ports[i]); - unregister_hdlc_device(dev); - } - - if (card->irq) - free_irq(card->irq, card); - - if (card->rambase) - iounmap(card->rambase); - if (card->scabase) - iounmap(card->scabase); - if (card->plxbase) - iounmap(card->plxbase); - - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - if (card->ports[0].dev) - free_netdev(card->ports[0].dev); - if (card->ports[1].dev) - free_netdev(card->ports[1].dev); - kfree(card); -} - - - -static int __devinit pc300_pci_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - card_t *card; - u8 rev_id; - u32 __iomem *p; - int i; - u32 ramsize; - u32 ramphys; /* buffer memory base */ - u32 scaphys; /* SCA memory base */ - u32 plxphys; /* PLX registers memory base */ - -#ifndef MODULE - static int printed_version; - if (!printed_version++) - printk(KERN_INFO "%s\n", version); -#endif - - i = pci_enable_device(pdev); - if (i) - return i; - - i = pci_request_regions(pdev, "PC300"); - if (i) { - pci_disable_device(pdev); - return i; - } - - card = kmalloc(sizeof(card_t), GFP_KERNEL); - if (card == NULL) { - printk(KERN_ERR "pc300: unable to allocate memory\n"); - pci_release_regions(pdev); - pci_disable_device(pdev); - return -ENOBUFS; - } - memset(card, 0, sizeof(card_t)); - pci_set_drvdata(pdev, card); - - if (pdev->device == PCI_DEVICE_ID_PC300_TE_1 || - pdev->device == PCI_DEVICE_ID_PC300_TE_2) - card->type = PC300_TE; /* not fully supported */ - else if (card->init_ctrl_value & PC300_CTYPE_MASK) - card->type = PC300_X21; - else - card->type = PC300_RSV; - - if (pdev->device == PCI_DEVICE_ID_PC300_RX_1 || - pdev->device == PCI_DEVICE_ID_PC300_TE_1) - card->n_ports = 1; - else - card->n_ports = 2; - - for (i = 0; i < card->n_ports; i++) - if (!(card->ports[i].dev = alloc_hdlcdev(&card->ports[i]))) { - printk(KERN_ERR "pc300: unable to allocate memory\n"); - pc300_pci_remove_one(pdev); - return -ENOMEM; - } - - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); - if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE || - pci_resource_len(pdev, 2) != PC300_SCA_SIZE || - pci_resource_len(pdev, 3) < 16384) { - printk(KERN_ERR "pc300: invalid card EEPROM parameters\n"); - pc300_pci_remove_one(pdev); - return -EFAULT; - } - - plxphys = pci_resource_start(pdev,0) & PCI_BASE_ADDRESS_MEM_MASK; - card->plxbase = ioremap(plxphys, PC300_PLX_SIZE); - - scaphys = pci_resource_start(pdev,2) & PCI_BASE_ADDRESS_MEM_MASK; - card->scabase = ioremap(scaphys, PC300_SCA_SIZE); - - ramphys = pci_resource_start(pdev,3) & PCI_BASE_ADDRESS_MEM_MASK; - card->rambase = ioremap(ramphys, pci_resource_len(pdev,3)); - - if (card->plxbase == NULL || - card->scabase == NULL || - card->rambase == NULL) { - printk(KERN_ERR "pc300: ioremap() failed\n"); - pc300_pci_remove_one(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); - pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, plxphys); - - /* Reset PLX */ - p = &card->plxbase->init_ctrl; - writel(card->init_ctrl_value | 0x40000000, p); - readl(p); /* Flush the write - do not use sca_flush */ - udelay(1); - - writel(card->init_ctrl_value, p); - readl(p); /* Flush the write - do not use sca_flush */ - udelay(1); - - /* Reload Config. Registers from EEPROM */ - writel(card->init_ctrl_value | 0x20000000, p); - readl(p); /* Flush the write - do not use sca_flush */ - udelay(1); - - writel(card->init_ctrl_value, p); - readl(p); /* Flush the write - do not use sca_flush */ - udelay(1); - - ramsize = sca_detect_ram(card, card->rambase, - pci_resource_len(pdev, 3)); - - if (use_crystal_clock) - card->init_ctrl_value &= ~PC300_CLKSEL_MASK; - else - card->init_ctrl_value |= PC300_CLKSEL_MASK; - - writel(card->init_ctrl_value, &card->plxbase->init_ctrl); - /* number of TX + RX buffers for one port */ - i = ramsize / (card->n_ports * (sizeof(pkt_desc) + HDLC_MAX_MRU)); - card->tx_ring_buffers = min(i / 2, MAX_TX_BUFFERS); - card->rx_ring_buffers = i - card->tx_ring_buffers; - - card->buff_offset = card->n_ports * sizeof(pkt_desc) * - (card->tx_ring_buffers + card->rx_ring_buffers); - - printk(KERN_INFO "pc300: PC300/%s, %u KB RAM at 0x%x, IRQ%u, " - "using %u TX + %u RX packets rings\n", - card->type == PC300_X21 ? "X21" : - card->type == PC300_TE ? "TE" : "RSV", - ramsize / 1024, ramphys, pdev->irq, - card->tx_ring_buffers, card->rx_ring_buffers); - - if (card->tx_ring_buffers < 1) { - printk(KERN_ERR "pc300: RAM test failed\n"); - pc300_pci_remove_one(pdev); - return -EFAULT; - } - - /* Enable interrupts on the PCI bridge, LINTi1 active low */ - writew(0x0041, &card->plxbase->intr_ctrl_stat); - - /* Allocate IRQ */ - if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, devname, card)) { - printk(KERN_WARNING "pc300: could not allocate IRQ%d.\n", - pdev->irq); - pc300_pci_remove_one(pdev); - return -EBUSY; - } - card->irq = pdev->irq; - - sca_init(card, 0); - - // COTE not set - allows better TX DMA settings - // sca_out(sca_in(PCR, card) | PCR_COTE, PCR, card); - - sca_out(0x10, BTCR, card); - - for (i = 0; i < card->n_ports; i++) { - port_t *port = &card->ports[i]; - struct net_device *dev = port_to_dev(port); - hdlc_device *hdlc = dev_to_hdlc(dev); - port->phy_node = i; - - spin_lock_init(&port->lock); - SET_MODULE_OWNER(dev); - dev->irq = card->irq; - dev->mem_start = ramphys; - dev->mem_end = ramphys + ramsize - 1; - dev->tx_queue_len = 50; - dev->do_ioctl = pc300_ioctl; - dev->open = pc300_open; - dev->stop = pc300_close; - hdlc->attach = sca_attach; - hdlc->xmit = sca_xmit; - port->settings.clock_type = CLOCK_EXT; - port->card = card; - if (card->type == PC300_X21) - port->iface = IF_IFACE_X21; - else - port->iface = IF_IFACE_V35; - - if (register_hdlc_device(dev)) { - printk(KERN_ERR "pc300: unable to register hdlc " - "device\n"); - port->card = NULL; - pc300_pci_remove_one(pdev); - return -ENOBUFS; - } - sca_init_sync_port(port); /* Set up SCA memory */ - - printk(KERN_INFO "%s: PC300 node %d\n", - dev->name, port->phy_node); - } - return 0; -} - - - -static struct pci_device_id pc300_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_1, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_2, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_TE_1, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_TE_2, PCI_ANY_ID, - PCI_ANY_ID, 0, 0, 0 }, - { 0, } -}; - - -static struct pci_driver pc300_pci_driver = { - name: "PC300", - id_table: pc300_pci_tbl, - probe: pc300_pci_init_one, - remove: pc300_pci_remove_one, -}; - - -static int __init pc300_init_module(void) -{ -#ifdef MODULE - printk(KERN_INFO "%s\n", version); -#endif - if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) { - printk(KERN_ERR "pc300: Invalid PCI clock frequency\n"); - return -EINVAL; - } - if (use_crystal_clock != 0 && use_crystal_clock != 1) { - printk(KERN_ERR "pc300: Invalid 'use_crystal_clock' value\n"); - return -EINVAL; - } - - CLOCK_BASE = use_crystal_clock ? 24576000 : pci_clock_freq; - - return pci_module_init(&pc300_pci_driver); -} - - - -static void __exit pc300_cleanup_module(void) -{ - pci_unregister_driver(&pc300_pci_driver); -} - -MODULE_AUTHOR("Krzysztof Halasa "); -MODULE_DESCRIPTION("Cyclades PC300 serial port driver"); -MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(pci, pc300_pci_tbl); -module_param(pci_clock_freq, int, 0444); -MODULE_PARM_DESC(pci_clock_freq, "System PCI clock frequency in Hz"); -module_param(use_crystal_clock, int, 0444); -MODULE_PARM_DESC(use_crystal_clock, - "Use 24.576 MHz clock instead of PCI clock"); -module_init(pc300_init_module); -module_exit(pc300_cleanup_module); diff --git a/trunk/drivers/net/wan/z85230.c b/trunk/drivers/net/wan/z85230.c index 8dbcf83bb5f3..59ddd21c3958 100644 --- a/trunk/drivers/net/wan/z85230.c +++ b/trunk/drivers/net/wan/z85230.c @@ -331,7 +331,8 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set) static void z8530_rx(struct z8530_channel *c) { u8 ch,stat; - + spin_lock(c->lock); + while(1) { /* FIFO empty ? */ @@ -389,6 +390,7 @@ static void z8530_rx(struct z8530_channel *c) */ write_zsctrl(c, ERR_RES); write_zsctrl(c, RES_H_IUS); + spin_unlock(c->lock); } @@ -404,6 +406,7 @@ static void z8530_rx(struct z8530_channel *c) static void z8530_tx(struct z8530_channel *c) { + spin_lock(c->lock); while(c->txcount) { /* FIFO full ? */ if(!(read_zsreg(c, R0)&4)) @@ -431,6 +434,7 @@ static void z8530_tx(struct z8530_channel *c) z8530_tx_done(c); write_zsctrl(c, RES_H_IUS); + spin_unlock(c->lock); } /** @@ -448,6 +452,7 @@ static void z8530_status(struct z8530_channel *chan) { u8 status, altered; + spin_lock(chan->lock); status=read_zsreg(chan, R0); altered=chan->status^status; @@ -482,6 +487,7 @@ static void z8530_status(struct z8530_channel *chan) } write_zsctrl(chan, RES_EXT_INT); write_zsctrl(chan, RES_H_IUS); + spin_unlock(chan->lock); } struct z8530_irqhandler z8530_sync= @@ -505,6 +511,7 @@ EXPORT_SYMBOL(z8530_sync); static void z8530_dma_rx(struct z8530_channel *chan) { + spin_lock(chan->lock); if(chan->rxdma_on) { /* Special condition check only */ @@ -527,6 +534,7 @@ static void z8530_dma_rx(struct z8530_channel *chan) /* DMA is off right now, drain the slow way */ z8530_rx(chan); } + spin_unlock(chan->lock); } /** @@ -539,6 +547,7 @@ static void z8530_dma_rx(struct z8530_channel *chan) static void z8530_dma_tx(struct z8530_channel *chan) { + spin_lock(chan->lock); if(!chan->dma_tx) { printk(KERN_WARNING "Hey who turned the DMA off?\n"); @@ -548,6 +557,7 @@ static void z8530_dma_tx(struct z8530_channel *chan) /* This shouldnt occur in DMA mode */ printk(KERN_ERR "DMA tx - bogus event!\n"); z8530_tx(chan); + spin_unlock(chan->lock); } /** @@ -586,6 +596,7 @@ static void z8530_dma_status(struct z8530_channel *chan) } } + spin_lock(chan->lock); if(altered&chan->dcdcheck) { if(status&chan->dcdcheck) @@ -607,6 +618,7 @@ static void z8530_dma_status(struct z8530_channel *chan) write_zsctrl(chan, RES_EXT_INT); write_zsctrl(chan, RES_H_IUS); + spin_unlock(chan->lock); } struct z8530_irqhandler z8530_dma_sync= diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h b/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h index 3a064def162e..8286678513b9 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -352,10 +352,6 @@ #define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040 #define BCM43xx_UCODEFLAG_JAPAN 0x0080 -/* Hardware Radio Enable masks */ -#define BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16) -#define BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4) - /* Generic-Interrupt reasons. */ #define BCM43xx_IRQ_READY (1 << 0) #define BCM43xx_IRQ_BEACON (1 << 1) @@ -762,8 +758,7 @@ struct bcm43xx_private { bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ short_preamble:1, /* TRUE, if short preamble is enabled. */ - firmware_norelease:1, /* Do not release the firmware. Used on suspend. */ - radio_hw_enable:1; /* TRUE if radio is hardware enabled */ + firmware_norelease:1; /* Do not release the firmware. Used on suspend. */ struct bcm43xx_stats stats; diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 8f198befba39..7d383a27b927 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -26,7 +26,6 @@ */ #include "bcm43xx_leds.h" -#include "bcm43xx_radio.h" #include "bcm43xx.h" #include @@ -109,7 +108,6 @@ static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm, switch (led_index) { case 0: led->behaviour = BCM43xx_LED_ACTIVITY; - led->activelow = 1; if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ) led->behaviour = BCM43xx_LED_RADIO_ALL; break; @@ -201,21 +199,20 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) turn_on = activity; break; case BCM43xx_LED_RADIO_ALL: - turn_on = radio->enabled && bcm43xx_is_hw_radio_enabled(bcm); + turn_on = radio->enabled; break; case BCM43xx_LED_RADIO_A: case BCM43xx_LED_BCM4303_2: - turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) && - phy->type == BCM43xx_PHYTYPE_A); + turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A); break; case BCM43xx_LED_RADIO_B: case BCM43xx_LED_BCM4303_1: - turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) && + turn_on = (radio->enabled && (phy->type == BCM43xx_PHYTYPE_B || phy->type == BCM43xx_PHYTYPE_G)); break; case BCM43xx_LED_MODE_BG: - if (phy->type == BCM43xx_PHYTYPE_G && bcm43xx_is_hw_radio_enabled(bcm) && + if (phy->type == BCM43xx_PHYTYPE_G && 1/*FIXME: using G rates.*/) turn_on = 1; break; diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 23aaf1ed8541..91b752e3d07e 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2441,9 +2441,6 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) if (err) goto err_gpio_cleanup; bcm43xx_radio_turn_on(bcm); - bcm->radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm); - dprintk(KERN_INFO PFX "Radio %s by hardware\n", - (bcm->radio_hw_enable == 0) ? "disabled" : "enabled"); bcm43xx_write16(bcm, 0x03E6, 0x0000); err = bcm43xx_phy_init(bcm); @@ -3177,25 +3174,10 @@ static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm) } static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) -{ - bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? - //TODO for APHY (temperature?) -} - -static void bcm43xx_periodic_every1sec(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int radio_hw_enable; - /* check if radio hardware enabled status changed */ - radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm); - if (unlikely(bcm->radio_hw_enable != radio_hw_enable)) { - bcm->radio_hw_enable = radio_hw_enable; - dprintk(KERN_INFO PFX "Radio hardware status changed to %s\n", - (radio_hw_enable == 0) ? "disabled" : "enabled"); - bcm43xx_leds_update(bcm, 0); - } if (phy->type == BCM43xx_PHYTYPE_G) { //TODO: update_aci_moving_average if (radio->aci_enable && radio->aci_wlan_automatic) { @@ -3219,21 +3201,21 @@ static void bcm43xx_periodic_every1sec(struct bcm43xx_private *bcm) //TODO: implement rev1 workaround } } + bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? + //TODO for APHY (temperature?) } static void do_periodic_work(struct bcm43xx_private *bcm) { - if (bcm->periodic_state % 120 == 0) + if (bcm->periodic_state % 8 == 0) bcm43xx_periodic_every120sec(bcm); - if (bcm->periodic_state % 60 == 0) + if (bcm->periodic_state % 4 == 0) bcm43xx_periodic_every60sec(bcm); - if (bcm->periodic_state % 30 == 0) + if (bcm->periodic_state % 2 == 0) bcm43xx_periodic_every30sec(bcm); - if (bcm->periodic_state % 15 == 0) - bcm43xx_periodic_every15sec(bcm); - bcm43xx_periodic_every1sec(bcm); + bcm43xx_periodic_every15sec(bcm); - schedule_delayed_work(&bcm->periodic_work, HZ); + schedule_delayed_work(&bcm->periodic_work, HZ * 15); } static void bcm43xx_periodic_work_handler(struct work_struct *work) @@ -3246,7 +3228,7 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work) unsigned long orig_trans_start = 0; mutex_lock(&bcm->mutex); - if (unlikely(bcm->periodic_state % 60 == 0)) { + if (unlikely(bcm->periodic_state % 4 == 0)) { /* Periodic work will take a long time, so we want it to * be preemtible. */ @@ -3278,7 +3260,7 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work) do_periodic_work(bcm); - if (unlikely(bcm->periodic_state % 60 == 0)) { + if (unlikely(bcm->periodic_state % 4 == 0)) { spin_lock_irqsave(&bcm->irq_lock, flags); tasklet_enable(&bcm->isr_tasklet); bcm43xx_interrupt_enable(bcm, savedirqs); diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index af19a07032a3..bb9c484d7e19 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -1981,7 +1981,6 @@ void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) } radio->enabled = 1; dprintk(KERN_INFO PFX "Radio turned on\n"); - bcm43xx_leds_update(bcm, 0); } void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) @@ -2002,7 +2001,6 @@ void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0015, 0xAA00); radio->enabled = 0; dprintk(KERN_INFO PFX "Radio turned off\n"); - bcm43xx_leds_update(bcm, 0); } void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm) diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_radio.h index 77a98a53a2e2..9ed18039fa3e 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_radio.h +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_radio.h @@ -65,22 +65,6 @@ void bcm43xx_radio_init2060(struct bcm43xx_private *bcm); void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm); void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm); -static inline -int bcm43xx_is_hw_radio_enabled(struct bcm43xx_private *bcm) -{ - /* function to return state of hardware enable of radio - * returns 0 if radio disabled, 1 if radio enabled - */ - if (bcm->current_core->rev >= 3) - return ((bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) - & BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK) - == 0) ? 1 : 0; - else - return ((bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) - & BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK) - == 0) ? 0 : 1; -} - int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel, int synthetic_pu_workaround); diff --git a/trunk/drivers/net/wireless/hostap/hostap_main.c b/trunk/drivers/net/wireless/hostap/hostap_main.c index 9077e6edde34..04c19cefa1da 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_main.c +++ b/trunk/drivers/net/wireless/hostap/hostap_main.c @@ -84,7 +84,7 @@ struct net_device * hostap_add_interface(struct local_info *local, if (strchr(dev->name, '%')) ret = dev_alloc_name(dev, dev->name); - SET_NETDEV_DEV(dev, mdev->dev.parent); + SET_NETDEV_DEV(dev, mdev->class_dev.dev); if (ret >= 0) ret = register_netdevice(dev); diff --git a/trunk/drivers/net/wireless/ipw2200.c b/trunk/drivers/net/wireless/ipw2200.c index c878a2f3239c..22cb3fb7502e 100644 --- a/trunk/drivers/net/wireless/ipw2200.c +++ b/trunk/drivers/net/wireless/ipw2200.c @@ -9166,7 +9166,7 @@ static int ipw_wx_set_rts(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); mutex_lock(&priv->mutex); - if (wrqu->rts.disabled || !wrqu->rts.fixed) + if (wrqu->rts.disabled) priv->rts_threshold = DEFAULT_RTS_THRESHOLD; else { if (wrqu->rts.value < MIN_RTS_THRESHOLD || @@ -9255,7 +9255,7 @@ static int ipw_wx_set_frag(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); mutex_lock(&priv->mutex); - if (wrqu->frag.disabled || !wrqu->frag.fixed) + if (wrqu->frag.disabled) priv->ieee->fts = DEFAULT_FTS; else { if (wrqu->frag.value < MIN_FRAG_THRESHOLD || diff --git a/trunk/drivers/net/wireless/orinoco.c b/trunk/drivers/net/wireless/orinoco.c index 4e7f6cf51436..936c888e03e1 100644 --- a/trunk/drivers/net/wireless/orinoco.c +++ b/trunk/drivers/net/wireless/orinoco.c @@ -2059,7 +2059,7 @@ static int determine_firmware(struct net_device *dev) int err; struct comp_id nic_id, sta_id; unsigned int firmver; - char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2))); + char tmp[SYMBOL_MAX_VER_LEN+1]; /* Get the hardware version */ err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id); @@ -4293,8 +4293,8 @@ static void orinoco_get_drvinfo(struct net_device *dev, strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1); strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1); strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1); - if (dev->dev.parent) - strncpy(info->bus_info, dev->dev.parent->bus_id, + if (dev->class_dev.dev) + strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info) - 1); else snprintf(info->bus_info, sizeof(info->bus_info) - 1, diff --git a/trunk/drivers/net/wireless/orinoco_cs.c b/trunk/drivers/net/wireless/orinoco_cs.c index d1e502236b2a..d08ae8d2726c 100644 --- a/trunk/drivers/net/wireless/orinoco_cs.c +++ b/trunk/drivers/net/wireless/orinoco_cs.c @@ -332,7 +332,7 @@ orinoco_cs_config(struct pcmcia_device *link) /* Finally, report what we've done */ printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " - "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id, + "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id, link->irq.AssignedIRQ, link->io.BasePort1, link->io.BasePort1 + link->io.NumPorts1 - 1); diff --git a/trunk/drivers/net/wireless/prism54/islpci_dev.c b/trunk/drivers/net/wireless/prism54/islpci_dev.c index a037b11dac9d..f057fd9fcd79 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_dev.c +++ b/trunk/drivers/net/wireless/prism54/islpci_dev.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -788,17 +787,6 @@ islpci_set_multicast_list(struct net_device *dev) } #endif -static void islpci_ethtool_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); -} - -static struct ethtool_ops islpci_ethtool_ops = { - .get_drvinfo = islpci_ethtool_get_drvinfo, -}; - struct net_device * islpci_setup(struct pci_dev *pdev) { @@ -825,7 +813,6 @@ islpci_setup(struct pci_dev *pdev) ndev->do_ioctl = &prism54_ioctl; ndev->wireless_handlers = (struct iw_handler_def *) &prism54_handler_def; - ndev->ethtool_ops = &islpci_ethtool_ops; ndev->hard_start_xmit = &islpci_eth_transmit; /* ndev->set_multicast_list = &islpci_set_multicast_list; */ diff --git a/trunk/drivers/net/wireless/prism54/islpci_dev.h b/trunk/drivers/net/wireless/prism54/islpci_dev.h index 736666da6c24..a9aa1662eaa4 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_dev.h +++ b/trunk/drivers/net/wireless/prism54/islpci_dev.h @@ -211,8 +211,4 @@ islpci_trigger(islpci_private *priv) int islpci_free_memory(islpci_private *); struct net_device *islpci_setup(struct pci_dev *); - -#define DRV_NAME "prism54" -#define DRV_VERSION "1.2" - #endif /* _ISLPCI_DEV_H */ diff --git a/trunk/drivers/net/wireless/prism54/islpci_hotplug.c b/trunk/drivers/net/wireless/prism54/islpci_hotplug.c index 3dcb13bb7d57..58257b40c043 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/trunk/drivers/net/wireless/prism54/islpci_hotplug.c @@ -28,6 +28,9 @@ #include "islpci_mgt.h" /* for pc_debug */ #include "isl_oid.h" +#define DRV_NAME "prism54" +#define DRV_VERSION "1.2" + MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team "); MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/wireless/spectrum_cs.c b/trunk/drivers/net/wireless/spectrum_cs.c index af70460f008a..cf2d1486b01d 100644 --- a/trunk/drivers/net/wireless/spectrum_cs.c +++ b/trunk/drivers/net/wireless/spectrum_cs.c @@ -806,7 +806,7 @@ spectrum_cs_config(struct pcmcia_device *link) /* Finally, report what we've done */ printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io " - "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id, + "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id, link->irq.AssignedIRQ, link->io.BasePort1, link->io.BasePort1 + link->io.NumPorts1 - 1); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c index 12dfc0b6efe6..78ea72fb8f0c 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c @@ -84,18 +84,6 @@ static void print_id(struct zd_chip *chip) dev_info(zd_chip_dev(chip), "%s\n", buffer); } -static zd_addr_t inc_addr(zd_addr_t addr) -{ - u16 a = (u16)addr; - /* Control registers use byte addressing, but everything else uses word - * addressing. */ - if ((a & 0xf000) == CR_START) - a += 2; - else - a += 1; - return (zd_addr_t)a; -} - /* Read a variable number of 32-bit values. Parameter count is not allowed to * exceed USB_MAX_IOREAD32_COUNT. */ @@ -126,7 +114,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr for (i = 0; i < count; i++) { int j = 2*i; /* We read the high word always first. */ - a16[j] = inc_addr(addr[i]); + a16[j] = zd_inc_word(addr[i]); a16[j+1] = addr[i]; } @@ -175,7 +163,7 @@ int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, j = 2*i; /* We write the high word always first. */ ioreqs16[j].value = ioreqs[i].value >> 16; - ioreqs16[j].addr = inc_addr(ioreqs[i].addr); + ioreqs16[j].addr = zd_inc_word(ioreqs[i].addr); ioreqs16[j+1].value = ioreqs[i].value; ioreqs16[j+1].addr = ioreqs[i].addr; } @@ -478,8 +466,7 @@ static int read_values(struct zd_chip *chip, u8 *values, size_t count, ZD_ASSERT(mutex_is_locked(&chip->mutex)); for (i = 0;;) { - r = zd_ioread32_locked(chip, &v, - (zd_addr_t)((u16)e2p_addr+i/2)); + r = zd_ioread32_locked(chip, &v, e2p_addr+i/2); if (r) return r; v -= guard; @@ -811,18 +798,47 @@ static int hw_reset_phy(struct zd_chip *chip) static int zd1211_hw_init_hmac(struct zd_chip *chip) { static const struct zd_ioreq32 ioreqs[] = { + { CR_ACK_TIMEOUT_EXT, 0x20 }, + { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, { CR_ZD1211_RETRY_MAX, 0x2 }, + { CR_SNIFFER_ON, 0 }, + { CR_RX_FILTER, STA_RX_FILTER }, + { CR_GROUP_HASH_P1, 0x00 }, + { CR_GROUP_HASH_P2, 0x80000000 }, + { CR_REG1, 0xa4 }, + { CR_ADDA_PWR_DWN, 0x7f }, + { CR_BCN_PLCP_CFG, 0x00f00401 }, + { CR_PHY_DELAY, 0x00 }, + { CR_ACK_TIMEOUT_EXT, 0x80 }, + { CR_ADDA_PWR_DWN, 0x00 }, + { CR_ACK_TIME_80211, 0x100 }, + { CR_RX_PE_DELAY, 0x70 }, + { CR_PS_CTRL, 0x10000000 }, + { CR_RTS_CTS_RATE, 0x02030203 }, { CR_RX_THRESHOLD, 0x000c0640 }, + { CR_AFTER_PNP, 0x1 }, + { CR_WEP_PROTECT, 0x114 }, }; + int r; + dev_dbg_f(zd_chip_dev(chip), "\n"); ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); + r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +#ifdef DEBUG + if (r) { + dev_err(zd_chip_dev(chip), + "error in zd_iowrite32a_locked. Error number %d\n", r); + } +#endif /* DEBUG */ + return r; } static int zd1211b_hw_init_hmac(struct zd_chip *chip) { static const struct zd_ioreq32 ioreqs[] = { + { CR_ACK_TIMEOUT_EXT, 0x20 }, + { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, { CR_ZD1211B_RETRY_MAX, 0x02020202 }, { CR_ZD1211B_TX_PWR_CTL4, 0x007f003f }, { CR_ZD1211B_TX_PWR_CTL3, 0x007f003f }, @@ -831,20 +847,6 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip) { CR_ZD1211B_AIFS_CTL1, 0x00280028 }, { CR_ZD1211B_AIFS_CTL2, 0x008C003C }, { CR_ZD1211B_TXOP, 0x01800824 }, - { CR_RX_THRESHOLD, 0x000c0eff, }, - }; - - dev_dbg_f(zd_chip_dev(chip), "\n"); - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int hw_init_hmac(struct zd_chip *chip) -{ - int r; - static const struct zd_ioreq32 ioreqs[] = { - { CR_ACK_TIMEOUT_EXT, 0x20 }, - { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, { CR_SNIFFER_ON, 0 }, { CR_RX_FILTER, STA_RX_FILTER }, { CR_GROUP_HASH_P1, 0x00 }, @@ -859,16 +861,25 @@ static int hw_init_hmac(struct zd_chip *chip) { CR_RX_PE_DELAY, 0x70 }, { CR_PS_CTRL, 0x10000000 }, { CR_RTS_CTS_RATE, 0x02030203 }, + { CR_RX_THRESHOLD, 0x000c0eff, }, { CR_AFTER_PNP, 0x1 }, { CR_WEP_PROTECT, 0x114 }, - { CR_IFS_VALUE, IFS_VALUE_DEFAULT }, }; + int r; + + dev_dbg_f(zd_chip_dev(chip), "\n"); ZD_ASSERT(mutex_is_locked(&chip->mutex)); r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - return r; + if (r) { + dev_dbg_f(zd_chip_dev(chip), + "error in zd_iowrite32a_locked. Error number %d\n", r); + } + return r; +} +static int hw_init_hmac(struct zd_chip *chip) +{ return chip->is_zd1211b ? zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip); } @@ -963,12 +974,14 @@ static int hw_init(struct zd_chip *chip) if (r) return r; - return set_beacon_interval(chip, 100); -} + /* Although the vendor driver defaults to a different value during + * init, it overwrites the IFS value with the following every time + * the channel changes. We should aim to be more intelligent... */ + r = zd_iowrite32_locked(chip, IFS_VALUE_DEFAULT, CR_IFS_VALUE); + if (r) + return r; -static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset) -{ - return (zd_addr_t)((u16)chip->fw_regs_base + offset); + return set_beacon_interval(chip, 100); } #ifdef DEBUG @@ -1005,11 +1018,9 @@ static int test_init(struct zd_chip *chip) static void dump_fw_registers(struct zd_chip *chip) { - const zd_addr_t addr[4] = { - fw_reg_addr(chip, FW_REG_FIRMWARE_VER), - fw_reg_addr(chip, FW_REG_USB_SPEED), - fw_reg_addr(chip, FW_REG_FIX_TX_RATE), - fw_reg_addr(chip, FW_REG_LED_LINK_STATUS), + static const zd_addr_t addr[4] = { + FW_FIRMWARE_VER, FW_USB_SPEED, FW_FIX_TX_RATE, + FW_LINK_STATUS }; int r; @@ -1035,8 +1046,7 @@ static int print_fw_version(struct zd_chip *chip) int r; u16 version; - r = zd_ioread16_locked(chip, &version, - fw_reg_addr(chip, FW_REG_FIRMWARE_VER)); + r = zd_ioread16_locked(chip, &version, FW_FIRMWARE_VER); if (r) return r; @@ -1116,22 +1126,6 @@ int zd_chip_disable_hwint(struct zd_chip *chip) return r; } -static int read_fw_regs_offset(struct zd_chip *chip) -{ - int r; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = zd_ioread16_locked(chip, (u16*)&chip->fw_regs_base, - FWRAW_REGS_ADDR); - if (r) - return r; - dev_dbg_f(zd_chip_dev(chip), "fw_regs_base: %#06hx\n", - (u16)chip->fw_regs_base); - - return 0; -} - - int zd_chip_init_hw(struct zd_chip *chip, u8 device_type) { int r; @@ -1151,7 +1145,7 @@ int zd_chip_init_hw(struct zd_chip *chip, u8 device_type) if (r) goto out; - r = read_fw_regs_offset(chip); + r = zd_usb_init_hw(&chip->usb); if (r) goto out; @@ -1331,15 +1325,15 @@ u8 zd_chip_get_channel(struct zd_chip *chip) int zd_chip_control_leds(struct zd_chip *chip, enum led_status status) { - const zd_addr_t a[] = { - fw_reg_addr(chip, FW_REG_LED_LINK_STATUS), + static const zd_addr_t a[] = { + FW_LINK_STATUS, CR_LED, }; int r; u16 v[ARRAY_SIZE(a)]; struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = { - [0] = { fw_reg_addr(chip, FW_REG_LED_LINK_STATUS) }, + [0] = { FW_LINK_STATUS }, [1] = { CR_LED }, }; u16 other_led; diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h index b07569e391ee..a4e3cee9b59d 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h @@ -18,6 +18,7 @@ #ifndef _ZD_CHIP_H #define _ZD_CHIP_H +#include "zd_types.h" #include "zd_rf.h" #include "zd_usb.h" @@ -26,37 +27,6 @@ * adds a processor for handling the USB protocol. */ -/* Address space */ -enum { - /* CONTROL REGISTERS */ - CR_START = 0x9000, - - - /* FIRMWARE */ - FW_START = 0xee00, - - - /* EEPROM */ - E2P_START = 0xf800, - E2P_LEN = 0x800, - - /* EEPROM layout */ - E2P_LOAD_CODE_LEN = 0xe, /* base 0xf800 */ - E2P_LOAD_VECT_LEN = 0x9, /* base 0xf80e */ - /* E2P_DATA indexes into this */ - E2P_DATA_LEN = 0x7e, /* base 0xf817 */ - E2P_BOOT_CODE_LEN = 0x760, /* base 0xf895 */ - E2P_INTR_VECT_LEN = 0xb, /* base 0xfff5 */ - - /* Some precomputed offsets into the EEPROM */ - E2P_DATA_OFFSET = E2P_LOAD_CODE_LEN + E2P_LOAD_VECT_LEN, - E2P_BOOT_CODE_OFFSET = E2P_DATA_OFFSET + E2P_DATA_LEN, -}; - -#define CTL_REG(offset) ((zd_addr_t)(CR_START + (offset))) -#define E2P_DATA(offset) ((zd_addr_t)(E2P_START + E2P_DATA_OFFSET + (offset))) -#define FWRAW_DATA(offset) ((zd_addr_t)(FW_START + (offset))) - /* 8-bit hardware registers */ #define CR0 CTL_REG(0x0000) #define CR1 CTL_REG(0x0004) @@ -332,7 +302,7 @@ enum { #define CR_MAX_PHY_REG 255 -/* Taken from the ZYDAS driver, not all of them are relevant for the ZD1211 +/* Taken from the ZYDAS driver, not all of them are relevant for the ZSD1211 * driver. */ @@ -624,70 +594,80 @@ enum { /* * Upper 16 bit contains the regulatory domain. */ -#define E2P_SUBID E2P_DATA(0x00) -#define E2P_POD E2P_DATA(0x02) -#define E2P_MAC_ADDR_P1 E2P_DATA(0x04) -#define E2P_MAC_ADDR_P2 E2P_DATA(0x06) -#define E2P_PWR_CAL_VALUE1 E2P_DATA(0x08) -#define E2P_PWR_CAL_VALUE2 E2P_DATA(0x0a) -#define E2P_PWR_CAL_VALUE3 E2P_DATA(0x0c) -#define E2P_PWR_CAL_VALUE4 E2P_DATA(0x0e) -#define E2P_PWR_INT_VALUE1 E2P_DATA(0x10) -#define E2P_PWR_INT_VALUE2 E2P_DATA(0x12) -#define E2P_PWR_INT_VALUE3 E2P_DATA(0x14) -#define E2P_PWR_INT_VALUE4 E2P_DATA(0x16) +#define E2P_SUBID E2P_REG(0x00) +#define E2P_POD E2P_REG(0x02) +#define E2P_MAC_ADDR_P1 E2P_REG(0x04) +#define E2P_MAC_ADDR_P2 E2P_REG(0x06) +#define E2P_PWR_CAL_VALUE1 E2P_REG(0x08) +#define E2P_PWR_CAL_VALUE2 E2P_REG(0x0a) +#define E2P_PWR_CAL_VALUE3 E2P_REG(0x0c) +#define E2P_PWR_CAL_VALUE4 E2P_REG(0x0e) +#define E2P_PWR_INT_VALUE1 E2P_REG(0x10) +#define E2P_PWR_INT_VALUE2 E2P_REG(0x12) +#define E2P_PWR_INT_VALUE3 E2P_REG(0x14) +#define E2P_PWR_INT_VALUE4 E2P_REG(0x16) /* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30) * also only 11 channels. */ -#define E2P_ALLOWED_CHANNEL E2P_DATA(0x18) - -#define E2P_PHY_REG E2P_DATA(0x1a) -#define E2P_DEVICE_VER E2P_DATA(0x20) -#define E2P_36M_CAL_VALUE1 E2P_DATA(0x28) -#define E2P_36M_CAL_VALUE2 E2P_DATA(0x2a) -#define E2P_36M_CAL_VALUE3 E2P_DATA(0x2c) -#define E2P_36M_CAL_VALUE4 E2P_DATA(0x2e) -#define E2P_11A_INT_VALUE1 E2P_DATA(0x30) -#define E2P_11A_INT_VALUE2 E2P_DATA(0x32) -#define E2P_11A_INT_VALUE3 E2P_DATA(0x34) -#define E2P_11A_INT_VALUE4 E2P_DATA(0x36) -#define E2P_48M_CAL_VALUE1 E2P_DATA(0x38) -#define E2P_48M_CAL_VALUE2 E2P_DATA(0x3a) -#define E2P_48M_CAL_VALUE3 E2P_DATA(0x3c) -#define E2P_48M_CAL_VALUE4 E2P_DATA(0x3e) -#define E2P_48M_INT_VALUE1 E2P_DATA(0x40) -#define E2P_48M_INT_VALUE2 E2P_DATA(0x42) -#define E2P_48M_INT_VALUE3 E2P_DATA(0x44) -#define E2P_48M_INT_VALUE4 E2P_DATA(0x46) -#define E2P_54M_CAL_VALUE1 E2P_DATA(0x48) /* ??? */ -#define E2P_54M_CAL_VALUE2 E2P_DATA(0x4a) -#define E2P_54M_CAL_VALUE3 E2P_DATA(0x4c) -#define E2P_54M_CAL_VALUE4 E2P_DATA(0x4e) -#define E2P_54M_INT_VALUE1 E2P_DATA(0x50) -#define E2P_54M_INT_VALUE2 E2P_DATA(0x52) -#define E2P_54M_INT_VALUE3 E2P_DATA(0x54) -#define E2P_54M_INT_VALUE4 E2P_DATA(0x56) - -/* This word contains the base address of the FW_REG_ registers below */ -#define FWRAW_REGS_ADDR FWRAW_DATA(0x1d) - -/* All 16 bit values, offset from the address in FWRAW_REGS_ADDR */ -enum { - FW_REG_FIRMWARE_VER = 0, - /* non-zero if USB high speed connection */ - FW_REG_USB_SPEED = 1, - FW_REG_FIX_TX_RATE = 2, - /* Seems to be able to control LEDs over the firmware */ - FW_REG_LED_LINK_STATUS = 3, - FW_REG_SOFT_RESET = 4, - FW_REG_FLASH_CHK = 5, -}; +#define E2P_ALLOWED_CHANNEL E2P_REG(0x18) + +#define E2P_PHY_REG E2P_REG(0x1a) +#define E2P_DEVICE_VER E2P_REG(0x20) +#define E2P_36M_CAL_VALUE1 E2P_REG(0x28) +#define E2P_36M_CAL_VALUE2 E2P_REG(0x2a) +#define E2P_36M_CAL_VALUE3 E2P_REG(0x2c) +#define E2P_36M_CAL_VALUE4 E2P_REG(0x2e) +#define E2P_11A_INT_VALUE1 E2P_REG(0x30) +#define E2P_11A_INT_VALUE2 E2P_REG(0x32) +#define E2P_11A_INT_VALUE3 E2P_REG(0x34) +#define E2P_11A_INT_VALUE4 E2P_REG(0x36) +#define E2P_48M_CAL_VALUE1 E2P_REG(0x38) +#define E2P_48M_CAL_VALUE2 E2P_REG(0x3a) +#define E2P_48M_CAL_VALUE3 E2P_REG(0x3c) +#define E2P_48M_CAL_VALUE4 E2P_REG(0x3e) +#define E2P_48M_INT_VALUE1 E2P_REG(0x40) +#define E2P_48M_INT_VALUE2 E2P_REG(0x42) +#define E2P_48M_INT_VALUE3 E2P_REG(0x44) +#define E2P_48M_INT_VALUE4 E2P_REG(0x46) +#define E2P_54M_CAL_VALUE1 E2P_REG(0x48) /* ??? */ +#define E2P_54M_CAL_VALUE2 E2P_REG(0x4a) +#define E2P_54M_CAL_VALUE3 E2P_REG(0x4c) +#define E2P_54M_CAL_VALUE4 E2P_REG(0x4e) +#define E2P_54M_INT_VALUE1 E2P_REG(0x50) +#define E2P_54M_INT_VALUE2 E2P_REG(0x52) +#define E2P_54M_INT_VALUE3 E2P_REG(0x54) +#define E2P_54M_INT_VALUE4 E2P_REG(0x56) + +/* All 16 bit values */ +#define FW_FIRMWARE_VER FW_REG(0) +/* non-zero if USB high speed connection */ +#define FW_USB_SPEED FW_REG(1) +#define FW_FIX_TX_RATE FW_REG(2) +/* Seems to be able to control LEDs over the firmware */ +#define FW_LINK_STATUS FW_REG(3) +#define FW_SOFT_RESET FW_REG(4) +#define FW_FLASH_CHK FW_REG(5) -/* Values for FW_LINK_STATUS */ #define FW_LINK_OFF 0x0 #define FW_LINK_TX 0x1 /* 0x2 - link led on? */ +enum { + CR_BASE_OFFSET = 0x9000, + FW_START_OFFSET = 0xee00, + FW_BASE_ADDR_OFFSET = FW_START_OFFSET + 0x1d, + EEPROM_START_OFFSET = 0xf800, + EEPROM_SIZE = 0x800, /* words */ + LOAD_CODE_SIZE = 0xe, /* words */ + LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */ + EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE, + EEPROM_REGS_SIZE = 0x7e, /* words */ + E2P_BASE_OFFSET = EEPROM_START_OFFSET + + EEPROM_REGS_OFFSET, +}; + +#define FW_REG_TABLE_ADDR USB_ADDR(FW_START_OFFSET + 0x1d) + enum { /* indices for ofdm_cal_values */ OFDM_36M_INDEX = 0, @@ -699,8 +679,6 @@ struct zd_chip { struct zd_usb usb; struct zd_rf rf; struct mutex mutex; - /* Base address of FW_REG_ registers */ - zd_addr_t fw_regs_base; u8 e2p_mac[ETH_ALEN]; /* EepSetPoint in the vendor driver */ u8 pwr_cal_values[E2P_CHANNEL_COUNT]; diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_def.h b/trunk/drivers/net/wireless/zd1211rw/zd_def.h index deb99d1eaa77..fb22f62cf1f3 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_def.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_def.h @@ -23,8 +23,6 @@ #include #include -typedef u16 __nocast zd_addr_t; - #define dev_printk_f(level, dev, fmt, args...) \ dev_printk(level, dev, "%s() " fmt, __func__, ##args) diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/trunk/drivers/net/wireless/zd1211rw/zd_ieee80211.h index c4f36d39642b..26b8298dff8c 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_ieee80211.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_ieee80211.h @@ -2,6 +2,7 @@ #define _ZD_IEEE80211_H #include +#include "zd_types.h" /* Additional definitions from the standards. */ diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf.h b/trunk/drivers/net/wireless/zd1211rw/zd_rf.h index a57732eb69e1..676b3734f1ed 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf.h @@ -18,6 +18,8 @@ #ifndef _ZD_RF_H #define _ZD_RF_H +#include "zd_types.h" + #define UW2451_RF 0x2 #define UCHIP_RF 0x3 #define AL2230_RF 0x4 diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_types.h b/trunk/drivers/net/wireless/zd1211rw/zd_types.h new file mode 100644 index 000000000000..0155a1584ed3 --- /dev/null +++ b/trunk/drivers/net/wireless/zd1211rw/zd_types.h @@ -0,0 +1,71 @@ +/* zd_types.h + * + * 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 _ZD_TYPES_H +#define _ZD_TYPES_H + +#include + +/* We have three register spaces mapped into the overall USB address space of + * 64K words (16-bit values). There is the control register space of + * double-word registers, the eeprom register space and the firmware register + * space. The control register space is byte mapped, the others are word + * mapped. + * + * For that reason, we are using byte offsets for control registers and word + * offsets for everything else. + */ + +typedef u32 __nocast zd_addr_t; + +enum { + ADDR_BASE_MASK = 0xff000000, + ADDR_OFFSET_MASK = 0x0000ffff, + ADDR_ZERO_MASK = 0x00ff0000, + NULL_BASE = 0x00000000, + USB_BASE = 0x01000000, + CR_BASE = 0x02000000, + CR_MAX_OFFSET = 0x0b30, + E2P_BASE = 0x03000000, + E2P_MAX_OFFSET = 0x007e, + FW_BASE = 0x04000000, + FW_MAX_OFFSET = 0x0005, +}; + +#define ZD_ADDR_BASE(addr) ((u32)(addr) & ADDR_BASE_MASK) +#define ZD_OFFSET(addr) ((u32)(addr) & ADDR_OFFSET_MASK) + +#define ZD_ADDR(base, offset) \ + ((zd_addr_t)(((base) & ADDR_BASE_MASK) | ((offset) & ADDR_OFFSET_MASK))) + +#define ZD_NULL_ADDR ((zd_addr_t)0) +#define USB_REG(offset) ZD_ADDR(USB_BASE, offset) /* word addressing */ +#define CTL_REG(offset) ZD_ADDR(CR_BASE, offset) /* byte addressing */ +#define E2P_REG(offset) ZD_ADDR(E2P_BASE, offset) /* word addressing */ +#define FW_REG(offset) ZD_ADDR(FW_BASE, offset) /* word addressing */ + +static inline zd_addr_t zd_inc_word(zd_addr_t addr) +{ + u32 base = ZD_ADDR_BASE(addr); + u32 offset = ZD_OFFSET(addr); + + offset += base == CR_BASE ? 2 : 1; + + return base | offset; +} + +#endif /* _ZD_TYPES_H */ diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c index 75ef55624d7f..605e96e74057 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c @@ -58,10 +58,6 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, {} @@ -77,6 +73,96 @@ MODULE_DEVICE_TABLE(usb, usb_ids); #define FW_ZD1211_PREFIX "zd1211/zd1211_" #define FW_ZD1211B_PREFIX "zd1211/zd1211b_" +/* register address handling */ + +#ifdef DEBUG +static int check_addr(struct zd_usb *usb, zd_addr_t addr) +{ + u32 base = ZD_ADDR_BASE(addr); + u32 offset = ZD_OFFSET(addr); + + if ((u32)addr & ADDR_ZERO_MASK) + goto invalid_address; + switch (base) { + case USB_BASE: + break; + case CR_BASE: + if (offset > CR_MAX_OFFSET) { + dev_dbg(zd_usb_dev(usb), + "CR offset %#010x larger than" + " CR_MAX_OFFSET %#10x\n", + offset, CR_MAX_OFFSET); + goto invalid_address; + } + if (offset & 1) { + dev_dbg(zd_usb_dev(usb), + "CR offset %#010x is not a multiple of 2\n", + offset); + goto invalid_address; + } + break; + case E2P_BASE: + if (offset > E2P_MAX_OFFSET) { + dev_dbg(zd_usb_dev(usb), + "E2P offset %#010x larger than" + " E2P_MAX_OFFSET %#010x\n", + offset, E2P_MAX_OFFSET); + goto invalid_address; + } + break; + case FW_BASE: + if (!usb->fw_base_offset) { + dev_dbg(zd_usb_dev(usb), + "ERROR: fw base offset has not been set\n"); + return -EAGAIN; + } + if (offset > FW_MAX_OFFSET) { + dev_dbg(zd_usb_dev(usb), + "FW offset %#10x is larger than" + " FW_MAX_OFFSET %#010x\n", + offset, FW_MAX_OFFSET); + goto invalid_address; + } + break; + default: + dev_dbg(zd_usb_dev(usb), + "address has unsupported base %#010x\n", addr); + goto invalid_address; + } + + return 0; +invalid_address: + dev_dbg(zd_usb_dev(usb), + "ERROR: invalid address: %#010x\n", addr); + return -EINVAL; +} +#endif /* DEBUG */ + +static u16 usb_addr(struct zd_usb *usb, zd_addr_t addr) +{ + u32 base; + u16 offset; + + base = ZD_ADDR_BASE(addr); + offset = ZD_OFFSET(addr); + + ZD_ASSERT(check_addr(usb, addr) == 0); + + switch (base) { + case CR_BASE: + offset += CR_BASE_OFFSET; + break; + case E2P_BASE: + offset += E2P_BASE_OFFSET; + break; + case FW_BASE: + offset += usb->fw_base_offset; + break; + } + + return offset; +} + /* USB device initialization */ static int request_fw_file( @@ -209,13 +295,14 @@ static int handle_version_mismatch(struct usb_device *udev, u8 device_type, if (r) goto error; - r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START, REBOOT); + r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START_OFFSET, + REBOOT); if (r) goto error; - offset = (E2P_BOOT_CODE_OFFSET * sizeof(u16)); + offset = ((EEPROM_REGS_OFFSET + EEPROM_REGS_SIZE) * sizeof(u16)); r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset, - E2P_START + E2P_BOOT_CODE_OFFSET, REBOOT); + E2P_BASE_OFFSET + EEPROM_REGS_SIZE, REBOOT); /* At this point, the vendor driver downloads the whole firmware * image, hacks around with version IDs, and uploads it again, @@ -244,7 +331,7 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) if (r) goto error; - fw_bcdDevice = get_word(ub_fw->data, E2P_DATA_OFFSET); + fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET); if (fw_bcdDevice != bcdDevice) { dev_info(&udev->dev, @@ -270,7 +357,8 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) if (r) goto error; - r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START, REBOOT); + r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START_OFFSET, + REBOOT); if (r) { dev_err(&udev->dev, "Could not upload firmware code uph. Error number %d\n", @@ -770,7 +858,7 @@ static inline void init_usb_interrupt(struct zd_usb *usb) spin_lock_init(&intr->lock); intr->interval = int_urb_interval(zd_usb_to_usbdev(usb)); init_completion(&intr->read_regs.completion); - intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT); + intr->read_regs.cr_int_addr = cpu_to_le16(usb_addr(usb, CR_INTERRUPT)); } static inline void init_usb_rx(struct zd_usb *usb) @@ -802,6 +890,22 @@ void zd_usb_init(struct zd_usb *usb, struct net_device *netdev, init_usb_rx(usb); } +int zd_usb_init_hw(struct zd_usb *usb) +{ + int r; + struct zd_chip *chip = zd_usb_to_chip(usb); + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_ioread16_locked(chip, &usb->fw_base_offset, + USB_REG((u16)FW_BASE_ADDR_OFFSET)); + if (r) + return r; + dev_dbg_f(zd_usb_dev(usb), "fw_base_offset: %#06hx\n", + usb->fw_base_offset); + + return 0; +} + void zd_usb_clear(struct zd_usb *usb) { usb_set_intfdata(usb->intf, NULL); @@ -1149,7 +1253,7 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, return -ENOMEM; req->id = cpu_to_le16(USB_REQ_READ_REGS); for (i = 0; i < count; i++) - req->addr[i] = cpu_to_le16((u16)addresses[i]); + req->addr[i] = cpu_to_le16(usb_addr(usb, addresses[i])); udev = zd_usb_to_usbdev(usb); prepare_read_regs_int(usb); @@ -1214,7 +1318,7 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, req->id = cpu_to_le16(USB_REQ_WRITE_REGS); for (i = 0; i < count; i++) { struct reg_data *rw = &req->reg_writes[i]; - rw->addr = cpu_to_le16((u16)ioreqs[i].addr); + rw->addr = cpu_to_le16(usb_addr(usb, ioreqs[i].addr)); rw->value = cpu_to_le16(ioreqs[i].value); } diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.h b/trunk/drivers/net/wireless/zd1211rw/zd_usb.h index 506ea6a74393..317d37c36679 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.h @@ -25,6 +25,7 @@ #include #include "zd_def.h" +#include "zd_types.h" enum devicetype { DEVICE_ZD1211 = 0, @@ -180,14 +181,15 @@ struct zd_usb_tx { spinlock_t lock; }; -/* Contains the usb parts. The structure doesn't require a lock because intf - * will not be changed after initialization. +/* Contains the usb parts. The structure doesn't require a lock, because intf + * and fw_base_offset, will not be changed after initialization. */ struct zd_usb { struct zd_usb_interrupt intr; struct zd_usb_rx rx; struct zd_usb_tx tx; struct usb_interface *intf; + u16 fw_base_offset; }; #define zd_usb_dev(usb) (&usb->intf->dev) diff --git a/trunk/drivers/pci/hotplug/Kconfig b/trunk/drivers/pci/hotplug/Kconfig index be92695a7833..adce4204d87d 100644 --- a/trunk/drivers/pci/hotplug/Kconfig +++ b/trunk/drivers/pci/hotplug/Kconfig @@ -145,6 +145,15 @@ config HOTPLUG_PCI_SHPC When in doubt, say N. +config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE + bool "Use polling mechanism for hot-plug events (for testing purpose)" + depends on HOTPLUG_PCI_SHPC + help + Say Y here if you want to use the polling mechanism for hot-plug + events for early platform testing. + + When in doubt, say N. + config HOTPLUG_PCI_RPA tristate "RPA PCI Hotplug driver" depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE diff --git a/trunk/drivers/pci/hotplug/pciehp.h b/trunk/drivers/pci/hotplug/pciehp.h index d19fcae8a7c0..4fb12fcda563 100644 --- a/trunk/drivers/pci/hotplug/pciehp.h +++ b/trunk/drivers/pci/hotplug/pciehp.h @@ -44,20 +44,15 @@ extern int pciehp_poll_time; extern int pciehp_debug; extern int pciehp_force; -#define dbg(format, arg...) \ - do { \ - if (pciehp_debug) \ - printk("%s: " format, MY_NAME , ## arg); \ - } while (0) -#define err(format, arg...) \ - printk(KERN_ERR "%s: " format, MY_NAME , ## arg) -#define info(format, arg...) \ - printk(KERN_INFO "%s: " format, MY_NAME , ## arg) -#define warn(format, arg...) \ - printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) +/*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ +#define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) +#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) +#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) + -#define SLOT_NAME_SIZE 10 struct slot { + struct slot *next; u8 bus; u8 device; u32 number; @@ -68,8 +63,6 @@ struct slot { struct hpc_ops *hpc_ops; struct hotplug_slot *hotplug_slot; struct list_head slot_list; - char name[SLOT_NAME_SIZE]; - unsigned long last_emi_toggle; }; struct event_info { @@ -77,15 +70,34 @@ struct event_info { u8 hp_slot; }; +typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id); + +struct php_ctlr_state_s { + struct php_ctlr_state_s *pnext; + struct pci_dev *pci_dev; + unsigned int irq; + unsigned long flags; /* spinlock's */ + u32 slot_device_offset; + u32 num_slots; + struct timer_list int_poll_timer; /* Added for poll event */ + php_intr_callback_t attention_button_callback; + php_intr_callback_t switch_change_callback; + php_intr_callback_t presence_change_callback; + php_intr_callback_t power_fault_callback; + void *callback_instance_id; + struct ctrl_reg *creg; /* Ptr to controller register space */ +}; + #define MAX_EVENTS 10 struct controller { struct controller *next; struct mutex crit_sect; /* critical section mutex */ struct mutex ctrl_lock; /* controller lock */ + struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ struct pci_dev *pci_dev; - struct list_head slot_list; + struct pci_bus *pci_bus; struct event_info event_queue[MAX_EVENTS]; struct slot *slot; struct hpc_ops *hpc_ops; @@ -100,8 +112,6 @@ struct controller { u8 ctrlcap; u16 vendor_id; u8 cap_base; - struct timer_list poll_timer; - volatile int cmd_busy; }; #define INT_BUTTON_IGNORE 0 @@ -121,6 +131,8 @@ struct controller { #define POWERON_STATE 3 #define POWEROFF_STATE 4 +#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400 + /* Error messages */ #define INTERLOCK_OPEN 0x00000002 #define ADD_NOT_SUPPORTED 0x00000003 @@ -132,6 +144,10 @@ struct controller { #define WRONG_BUS_FREQUENCY 0x0000000D #define POWER_FAILURE 0x0000000E +#define REMOVE_NOT_SUPPORTED 0x00000003 + +#define DISABLE_CARD 1 + /* Field definitions in Slot Capabilities Register */ #define ATTN_BUTTN_PRSN 0x00000001 #define PWR_CTRL_PRSN 0x00000002 @@ -139,7 +155,6 @@ struct controller { #define ATTN_LED_PRSN 0x00000008 #define PWR_LED_PRSN 0x00000010 #define HP_SUPR_RM_SUP 0x00000020 -#define EMI_PRSN 0x00020000 #define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN) #define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN) @@ -147,65 +162,130 @@ struct controller { #define ATTN_LED(cap) (cap & ATTN_LED_PRSN) #define PWR_LED(cap) (cap & PWR_LED_PRSN) #define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) -#define EMI(cap) (cap & EMI_PRSN) - -extern int pciehp_event_start_thread(void); -extern void pciehp_event_stop_thread(void); -extern int pciehp_enable_slot(struct slot *slot); -extern int pciehp_disable_slot(struct slot *slot); -extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); -extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); -extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); -extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); -extern int pciehp_configure_device(struct slot *p_slot); -extern int pciehp_unconfigure_device(struct slot *p_slot); -int pcie_init(struct controller *ctrl, struct pcie_device *dev); + +/* + * error Messages + */ +#define msg_initialization_err "Initialization failure, error=%d\n" +#define msg_button_on "PCI slot #%s - powering on due to button press.\n" +#define msg_button_off "PCI slot #%s - powering off due to button press.\n" +#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" +#define msg_button_ignore "PCI slot #%s - button press ignored. (action in progress...)\n" + +/* controller functions */ +extern int pciehp_event_start_thread (void); +extern void pciehp_event_stop_thread (void); +extern int pciehp_enable_slot (struct slot *slot); +extern int pciehp_disable_slot (struct slot *slot); + +extern u8 pciehp_handle_attention_button (u8 hp_slot, void *inst_id); +extern u8 pciehp_handle_switch_change (u8 hp_slot, void *inst_id); +extern u8 pciehp_handle_presence_change (u8 hp_slot, void *inst_id); +extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); +/* extern void long_delay (int delay); */ + +/* pci functions */ +extern int pciehp_configure_device (struct slot *p_slot); +extern int pciehp_unconfigure_device (struct slot *p_slot); + + /* Global variables */ extern struct controller *pciehp_ctrl_list; +/* Inline functions */ + static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) { - struct slot *slot; + struct slot *p_slot, *tmp_slot = NULL; + + p_slot = ctrl->slot; - list_for_each_entry(slot, &ctrl->slot_list, slot_list) { - if (slot->device == device) - return slot; + while (p_slot && (p_slot->device != device)) { + tmp_slot = p_slot; + p_slot = p_slot->next; } + if (p_slot == NULL) { + err("ERROR: pciehp_find_slot device=0x%x\n", device); + p_slot = tmp_slot; + } + + return p_slot; +} + +static inline int wait_for_ctrl_irq(struct controller *ctrl) +{ + int retval = 0; + + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&ctrl->queue, &wait); + if (!pciehp_poll_mode) + /* Sleep for up to 1 second */ + msleep_interruptible(1000); + else + msleep_interruptible(2500); + + remove_wait_queue(&ctrl->queue, &wait); + if (signal_pending(current)) + retval = -EINTR; + + return retval; +} + +#define SLOT_NAME_SIZE 10 - err("%s: slot (device=0x%x) not found\n", __FUNCTION__, device); - return NULL; +static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) +{ + snprintf(buffer, buffer_size, "%04d_%04d", slot->bus, slot->number); } +enum php_ctlr_type { + PCI, + ISA, + ACPI +}; + +int pcie_init(struct controller *ctrl, struct pcie_device *dev); + +/* This has no meaning for PCI Express, as there is only 1 slot per port */ +int pcie_get_ctlr_slot_config(struct controller *ctrl, + int *num_ctlr_slots, + int *first_device_num, + int *physical_slot_num, + u8 *ctrlcap); + struct hpc_ops { - int (*power_on_slot)(struct slot *slot); - int (*power_off_slot)(struct slot *slot); - int (*get_power_status)(struct slot *slot, u8 *status); - int (*get_attention_status)(struct slot *slot, u8 *status); - int (*set_attention_status)(struct slot *slot, u8 status); - int (*get_latch_status)(struct slot *slot, u8 *status); - int (*get_adapter_status)(struct slot *slot, u8 *status); - int (*get_emi_status)(struct slot *slot, u8 *status); - int (*toggle_emi)(struct slot *slot); - int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); - int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed); - int (*get_max_lnk_width)(struct slot *slot, enum pcie_link_width *val); - int (*get_cur_lnk_width)(struct slot *slot, enum pcie_link_width *val); - int (*query_power_fault)(struct slot *slot); - void (*green_led_on)(struct slot *slot); - void (*green_led_off)(struct slot *slot); - void (*green_led_blink)(struct slot *slot); - void (*release_ctlr)(struct controller *ctrl); - int (*check_lnk_status)(struct controller *ctrl); + int (*power_on_slot) (struct slot *slot); + int (*power_off_slot) (struct slot *slot); + int (*get_power_status) (struct slot *slot, u8 *status); + int (*get_attention_status) (struct slot *slot, u8 *status); + int (*set_attention_status) (struct slot *slot, u8 status); + int (*get_latch_status) (struct slot *slot, u8 *status); + int (*get_adapter_status) (struct slot *slot, u8 *status); + + int (*get_max_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); + int (*get_cur_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); + + int (*get_max_lnk_width) (struct slot *slot, enum pcie_link_width *value); + int (*get_cur_lnk_width) (struct slot *slot, enum pcie_link_width *value); + + int (*query_power_fault) (struct slot *slot); + void (*green_led_on) (struct slot *slot); + void (*green_led_off) (struct slot *slot); + void (*green_led_blink) (struct slot *slot); + void (*release_ctlr) (struct controller *ctrl); + int (*check_lnk_status) (struct controller *ctrl); }; + #ifdef CONFIG_ACPI #include #include #include #include -#define pciehp_get_hp_hw_control_from_firmware(dev) \ +#define pciehp_get_hp_hw_control_from_firmware(dev) \ pciehp_acpi_get_hp_hw_control_from_firmware(dev) static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, struct hotplug_params *hpp) diff --git a/trunk/drivers/pci/hotplug/pciehp_core.c b/trunk/drivers/pci/hotplug/pciehp_core.c index a92eda6e02f6..f13f31323e85 100644 --- a/trunk/drivers/pci/hotplug/pciehp_core.c +++ b/trunk/drivers/pci/hotplug/pciehp_core.c @@ -34,7 +34,6 @@ #include #include "pciehp.h" #include -#include /* Global variables */ int pciehp_debug; @@ -88,95 +87,6 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { .get_cur_bus_speed = get_cur_bus_speed, }; -/* - * Check the status of the Electro Mechanical Interlock (EMI) - */ -static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value) -{ - struct slot *slot = hotplug_slot->private; - return (slot->hpc_ops->get_emi_status(slot, value)); -} - -/* - * sysfs interface for the Electro Mechanical Interlock (EMI) - * 1 == locked, 0 == unlocked - */ -static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf) -{ - int retval; - u8 value; - - retval = get_lock_status(slot, &value); - if (retval) - goto lock_read_exit; - retval = sprintf (buf, "%d\n", value); - -lock_read_exit: - return retval; -} - -/* - * Change the status of the Electro Mechanical Interlock (EMI) - * This is a toggle - in addition there must be at least 1 second - * in between toggles. - */ -static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status) -{ - struct slot *slot = hotplug_slot->private; - int retval; - u8 value; - - mutex_lock(&slot->ctrl->crit_sect); - - /* has it been >1 sec since our last toggle? */ - if ((get_seconds() - slot->last_emi_toggle) < 1) - return -EINVAL; - - /* see what our current state is */ - retval = get_lock_status(hotplug_slot, &value); - if (retval || (value == status)) - goto set_lock_exit; - - slot->hpc_ops->toggle_emi(slot); -set_lock_exit: - mutex_unlock(&slot->ctrl->crit_sect); - return 0; -} - -/* - * sysfs interface which allows the user to toggle the Electro Mechanical - * Interlock. Valid values are either 0 or 1. 0 == unlock, 1 == lock - */ -static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf, - size_t count) -{ - unsigned long llock; - u8 lock; - int retval = 0; - - llock = simple_strtoul(buf, NULL, 10); - lock = (u8)(llock & 0xff); - - switch (lock) { - case 0: - case 1: - retval = set_lock_status(slot, lock); - break; - default: - err ("%d is an invalid lock value\n", lock); - retval = -EINVAL; - } - if (retval) - return retval; - return count; -} - -static struct hotplug_slot_attribute hotplug_slot_attr_lock = { - .attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR}, - .show = lock_read_file, - .store = lock_write_file -}; - /** * release_slot - free up the memory used by a slot * @hotplug_slot: slot to free @@ -188,108 +98,148 @@ static void release_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } -static void make_slot_name(struct slot *slot) -{ - snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", - slot->bus, slot->number); -} - static int init_slots(struct controller *ctrl) { struct slot *slot; + struct hpc_ops *hpc_ops; struct hotplug_slot *hotplug_slot; - struct hotplug_slot_info *info; - int retval = -ENOMEM; - int i; + struct hotplug_slot_info *hotplug_slot_info; + u8 number_of_slots; + u8 slot_device; + u32 slot_number; + int result = -ENOMEM; - for (i = 0; i < ctrl->num_slots; i++) { + number_of_slots = ctrl->num_slots; + slot_device = ctrl->slot_device_offset; + slot_number = ctrl->first_slot; + + while (number_of_slots) { slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); - if (!hotplug_slot) + slot->hotplug_slot = + kzalloc(sizeof(*(slot->hotplug_slot)), + GFP_KERNEL); + if (!slot->hotplug_slot) goto error_slot; - slot->hotplug_slot = hotplug_slot; + hotplug_slot = slot->hotplug_slot; - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) + hotplug_slot->info = + kzalloc(sizeof(*(hotplug_slot->info)), + GFP_KERNEL); + if (!hotplug_slot->info) goto error_hpslot; - hotplug_slot->info = info; - - hotplug_slot->name = slot->name; + hotplug_slot_info = hotplug_slot->info; + hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); + if (!hotplug_slot->name) + goto error_info; - slot->hp_slot = i; slot->ctrl = ctrl; - slot->bus = ctrl->pci_dev->subordinate->number; - slot->device = ctrl->slot_device_offset + i; - slot->hpc_ops = ctrl->hpc_ops; + slot->bus = ctrl->slot_bus; + slot->device = slot_device; + slot->hpc_ops = hpc_ops = ctrl->hpc_ops; + slot->number = ctrl->first_slot; + slot->hp_slot = slot_device - ctrl->slot_device_offset; /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; hotplug_slot->release = &release_slot; - make_slot_name(slot); + make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot); hotplug_slot->ops = &pciehp_hotplug_slot_ops; - get_power_status(hotplug_slot, &info->power_status); - get_attention_status(hotplug_slot, &info->attention_status); - get_latch_status(hotplug_slot, &info->latch_status); - get_adapter_status(hotplug_slot, &info->adapter_status); + hpc_ops->get_power_status(slot, + &(hotplug_slot_info->power_status)); + hpc_ops->get_attention_status(slot, + &(hotplug_slot_info->attention_status)); + hpc_ops->get_latch_status(slot, + &(hotplug_slot_info->latch_status)); + hpc_ops->get_adapter_status(slot, + &(hotplug_slot_info->adapter_status)); dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " - "slot_device_offset=%x\n", slot->bus, slot->device, - slot->hp_slot, slot->number, ctrl->slot_device_offset); - retval = pci_hp_register(hotplug_slot); - if (retval) { - err ("pci_hp_register failed with error %d\n", retval); - goto error_info; - } - /* create additional sysfs entries */ - if (EMI(ctrl->ctrlcap)) { - retval = sysfs_create_file(&hotplug_slot->kobj, - &hotplug_slot_attr_lock.attr); - if (retval) { - pci_hp_deregister(hotplug_slot); - err("cannot create additional sysfs entries\n"); - goto error_info; - } + "slot_device_offset=%x\n", + slot->bus, slot->device, slot->hp_slot, slot->number, + ctrl->slot_device_offset); + result = pci_hp_register(hotplug_slot); + if (result) { + err ("pci_hp_register failed with error %d\n", result); + goto error_name; } - list_add(&slot->slot_list, &ctrl->slot_list); + slot->next = ctrl->slot; + ctrl->slot = slot; + + number_of_slots--; + slot_device++; + slot_number += ctrl->slot_num_inc; } return 0; + +error_name: + kfree(hotplug_slot->name); error_info: - kfree(info); + kfree(hotplug_slot_info); error_hpslot: kfree(hotplug_slot); error_slot: kfree(slot); error: - return retval; + return result; } -static void cleanup_slots(struct controller *ctrl) + +static int cleanup_slots (struct controller * ctrl) { - struct list_head *tmp; - struct list_head *next; - struct slot *slot; + struct slot *old_slot, *next_slot; + + old_slot = ctrl->slot; + ctrl->slot = NULL; - list_for_each_safe(tmp, next, &ctrl->slot_list) { - slot = list_entry(tmp, struct slot, slot_list); - list_del(&slot->slot_list); - if (EMI(ctrl->ctrlcap)) - sysfs_remove_file(&slot->hotplug_slot->kobj, - &hotplug_slot_attr_lock.attr); - pci_hp_deregister(slot->hotplug_slot); + while (old_slot) { + next_slot = old_slot->next; + pci_hp_deregister (old_slot->hotplug_slot); + old_slot = next_slot; } + + + return(0); } +static int get_ctlr_slot_config(struct controller *ctrl) +{ + int num_ctlr_slots; /* Not needed; PCI Express has 1 slot per port*/ + int first_device_num; /* Not needed */ + int physical_slot_num; + u8 ctrlcap; + int rc; + + rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &ctrlcap); + if (rc) { + err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); + return (-1); + } + + ctrl->num_slots = num_ctlr_slots; /* PCI Express has 1 slot per port */ + ctrl->slot_device_offset = first_device_num; + ctrl->first_slot = physical_slot_num; + ctrl->ctrlcap = ctrlcap; + + dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) ctrlcap(%x) for b:d (%x:%x)\n", + __FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, ctrlcap, + ctrl->bus, ctrl->device); + + return (0); +} + + /* * set_attention_status - Turns the Amber LED for a slot on, off or blink */ @@ -428,6 +378,8 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ int rc; struct controller *ctrl; struct slot *t_slot; + int first_device_num = 0 ; /* first PCI device number supported by this PCIE */ + int num_ctlr_slots; /* number of slots supported by this HPC */ u8 value; struct pci_dev *pdev; @@ -436,7 +388,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ err("%s : out of memory\n", __FUNCTION__); goto err_out_none; } - INIT_LIST_HEAD(&ctrl->slot_list); pdev = dev->port; ctrl->pci_dev = pdev; @@ -449,6 +400,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ pci_set_drvdata(pdev, ctrl); + ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); + if (!ctrl->pci_bus) { + err("%s: out of memory\n", __FUNCTION__); + rc = -ENOMEM; + goto err_out_unmap_mmio_region; + } + memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); ctrl->bus = pdev->bus->number; /* ctrl bus */ ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ @@ -457,14 +415,26 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__, ctrl->bus, ctrl->device, ctrl->function, pdev->irq); + /* + * Save configuration headers for this and subordinate PCI buses + */ + + rc = get_ctlr_slot_config(ctrl); + if (rc) { + err(msg_initialization_err, rc); + goto err_out_free_ctrl_bus; + } + first_device_num = ctrl->slot_device_offset; + num_ctlr_slots = ctrl->num_slots; + /* Setup the slot information structures */ rc = init_slots(ctrl); if (rc) { - err("%s: slot initialization failed\n", PCIE_MODULE_NAME); - goto err_out_release_ctlr; + err(msg_initialization_err, 6); + goto err_out_free_ctrl_slot; } - t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); + t_slot = pciehp_find_slot(ctrl, first_device_num); /* Finish setting up the hot plug ctrl device */ ctrl->next_event = 0; @@ -477,18 +447,32 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ pciehp_ctrl_list = ctrl; } + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->ctrl_lock); + t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ + if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ - if (rc) + if (rc) { + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); goto err_out_free_ctrl_slot; + } else + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); } + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); + return 0; err_out_free_ctrl_slot: cleanup_slots(ctrl); -err_out_release_ctlr: +err_out_free_ctrl_bus: + kfree(ctrl->pci_bus); +err_out_unmap_mmio_region: ctrl->hpc_ops->release_ctlr(ctrl); err_out_free_ctrl: kfree(ctrl); @@ -522,6 +506,8 @@ static void __exit unload_pciehpd(void) while (ctrl) { cleanup_slots(ctrl); + kfree (ctrl->pci_bus); + ctrl->hpc_ops->release_ctlr(ctrl); tctrl = ctrl; diff --git a/trunk/drivers/pci/hotplug/pciehp_ctrl.c b/trunk/drivers/pci/hotplug/pciehp_ctrl.c index 4283ef56dbd9..372c63e35aa9 100644 --- a/trunk/drivers/pci/hotplug/pciehp_ctrl.c +++ b/trunk/drivers/pci/hotplug/pciehp_ctrl.c @@ -48,8 +48,9 @@ static inline char *slot_name(struct slot *p_slot) return p_slot->hotplug_slot->name; } -u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) +u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) { + struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u8 rc = 0; u8 getstatus; @@ -100,8 +101,9 @@ u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) } -u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) +u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) { + struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u8 rc = 0; u8 getstatus; @@ -141,8 +143,9 @@ u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) return rc; } -u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) +u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) { + struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u8 presence_save, rc = 0; struct event_info *taskInfo; @@ -184,8 +187,9 @@ u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) return rc; } -u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) +u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) { + struct controller *ctrl = (struct controller *) inst_id; struct slot *p_slot; u8 rc = 0; struct event_info *taskInfo; @@ -229,25 +233,35 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) static void set_slot_off(struct controller *ctrl, struct slot * pslot) { + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->ctrl_lock); + /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ if (POWER_CTRL(ctrl->ctrlcap)) { if (pslot->hpc_ops->power_off_slot(pslot)) { - err("%s: Issue of Slot Power Off command failed\n", - __FUNCTION__); + err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); + mutex_unlock(&ctrl->ctrl_lock); return; } + wait_for_ctrl_irq (ctrl); } - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl->ctrlcap)) { pslot->hpc_ops->green_led_off(pslot); + wait_for_ctrl_irq (ctrl); + } - if (ATTN_LED(ctrl->ctrlcap)) { - if (pslot->hpc_ops->set_attention_status(pslot, 1)) { - err("%s: Issue of Set Attention Led command failed\n", - __FUNCTION__); + if (ATTN_LED(ctrl->ctrlcap)) { + if (pslot->hpc_ops->set_attention_status(pslot, 1)) { + err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); + mutex_unlock(&ctrl->ctrl_lock); return; } + wait_for_ctrl_irq (ctrl); } + + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); } /** @@ -260,7 +274,7 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) static int board_added(struct slot *p_slot) { u8 hp_slot; - int retval = 0; + int rc = 0; struct controller *ctrl = p_slot->ctrl; hp_slot = p_slot->device - ctrl->slot_device_offset; @@ -269,38 +283,53 @@ static int board_added(struct slot *p_slot) __FUNCTION__, p_slot->device, ctrl->slot_device_offset, hp_slot); + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->ctrl_lock); + if (POWER_CTRL(ctrl->ctrlcap)) { /* Power on slot */ - retval = p_slot->hpc_ops->power_on_slot(p_slot); - if (retval) - return retval; + rc = p_slot->hpc_ops->power_on_slot(p_slot); + if (rc) { + mutex_unlock(&ctrl->ctrl_lock); + return -1; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); } - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_blink(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); /* Wait for ~1 second */ - msleep(1000); + wait_for_ctrl_irq (ctrl); - /* Check link training status */ - retval = p_slot->hpc_ops->check_lnk_status(ctrl); - if (retval) { + /* Check link training status */ + rc = p_slot->hpc_ops->check_lnk_status(ctrl); + if (rc) { err("%s: Failed to check link status\n", __FUNCTION__); set_slot_off(ctrl, p_slot); - return retval; + return rc; } /* Check for a power fault */ if (p_slot->hpc_ops->query_power_fault(p_slot)) { dbg("%s: power fault detected\n", __FUNCTION__); - retval = POWER_FAILURE; + rc = POWER_FAILURE; goto err_exit; } - retval = pciehp_configure_device(p_slot); - if (retval) { + rc = pciehp_configure_device(p_slot); + if (rc) { err("Cannot add device 0x%x:%x\n", p_slot->bus, - p_slot->device); + p_slot->device); goto err_exit; } @@ -309,16 +338,26 @@ static int board_added(struct slot *p_slot) */ if (pcie_mch_quirk) pci_fixup_device(pci_fixup_final, ctrl->pci_dev); - if (PWR_LED(ctrl->ctrlcap)) - p_slot->hpc_ops->green_led_on(p_slot); + if (PWR_LED(ctrl->ctrlcap)) { + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->ctrl_lock); + p_slot->hpc_ops->green_led_on(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); + } return 0; err_exit: set_slot_off(ctrl, p_slot); - return retval; + return -1; } + /** * remove_board - Turns off slot and LED's * @@ -327,32 +366,44 @@ static int remove_board(struct slot *p_slot) { u8 device; u8 hp_slot; - int retval = 0; + int rc; struct controller *ctrl = p_slot->ctrl; - retval = pciehp_unconfigure_device(p_slot); - if (retval) - return retval; + if (pciehp_unconfigure_device(p_slot)) + return 1; device = p_slot->device; + hp_slot = p_slot->device - ctrl->slot_device_offset; p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->ctrl_lock); + if (POWER_CTRL(ctrl->ctrlcap)) { /* power off slot */ - retval = p_slot->hpc_ops->power_off_slot(p_slot); - if (retval) { - err("%s: Issue of Slot Disable command failed\n", - __FUNCTION__); - return retval; + rc = p_slot->hpc_ops->power_off_slot(p_slot); + if (rc) { + err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); + mutex_unlock(&ctrl->ctrl_lock); + return rc; } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); } - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl->ctrlcap)) { /* turn off Green LED */ p_slot->hpc_ops->green_led_off(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); return 0; } @@ -397,10 +448,18 @@ static void pciehp_pushbutton_thread(unsigned long slot) dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, p_slot->bus, p_slot->device); - if (pciehp_enable_slot(p_slot) && - PWR_LED(p_slot->ctrl->ctrlcap)) + if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { + /* Wait for exclusive access to hardware */ + mutex_lock(&p_slot->ctrl->ctrl_lock); + p_slot->hpc_ops->green_led_off(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + /* Done with exclusive hardware access */ + mutex_unlock(&p_slot->ctrl->ctrl_lock); + } p_slot->state = STATIC_STATE; } @@ -439,10 +498,18 @@ static void pciehp_surprise_rm_thread(unsigned long slot) dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, p_slot->bus, p_slot->device); - if (pciehp_enable_slot(p_slot) && - PWR_LED(p_slot->ctrl->ctrlcap)) + if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { + /* Wait for exclusive access to hardware */ + mutex_lock(&p_slot->ctrl->ctrl_lock); + p_slot->hpc_ops->green_led_off(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + /* Done with exclusive hardware access */ + mutex_unlock(&p_slot->ctrl->ctrl_lock); + } p_slot->state = STATIC_STATE; } @@ -553,24 +620,46 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: - if (PWR_LED(ctrl->ctrlcap)) + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->ctrl_lock); + + if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_on(p_slot); - - if (ATTN_LED(ctrl->ctrlcap)) + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + if (ATTN_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->set_attention_status(p_slot, 0); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); break; case BLINKINGON_STATE: - if (PWR_LED(ctrl->ctrlcap)) - p_slot->hpc_ops->green_led_off(p_slot); + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->ctrl_lock); - if (ATTN_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl->ctrlcap)) { + p_slot->hpc_ops->green_led_off(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + if (ATTN_LED(ctrl->ctrlcap)){ p_slot->hpc_ops->set_attention_status(p_slot, 0); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); + break; default: warn("Not a valid state\n"); return; } - info("PCI slot #%s - action canceled due to button press.\n", slot_name(p_slot)); + info(msg_button_cancel, slot_name(p_slot)); p_slot->state = STATIC_STATE; } /* ***********Button Pressed (No action on 1st press...) */ @@ -583,21 +672,34 @@ static void interrupt_event_handler(struct controller *ctrl) /* slot is on */ dbg("slot is on\n"); p_slot->state = BLINKINGOFF_STATE; - info("PCI slot #%s - powering off due to button press.\n", slot_name(p_slot)); + info(msg_button_off, slot_name(p_slot)); } else { /* slot is off */ dbg("slot is off\n"); p_slot->state = BLINKINGON_STATE; - info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot)); + info(msg_button_on, slot_name(p_slot)); } + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->ctrl_lock); + /* blink green LED and turn off amber */ - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_blink(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } - if (ATTN_LED(ctrl->ctrlcap)) + if (ATTN_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->set_attention_status(p_slot, 0); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); + init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; @@ -610,11 +712,21 @@ static void interrupt_event_handler(struct controller *ctrl) else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { if (POWER_CTRL(ctrl->ctrlcap)) { dbg("power fault\n"); - if (ATTN_LED(ctrl->ctrlcap)) + /* Wait for exclusive access to hardware */ + mutex_lock(&ctrl->ctrl_lock); + + if (ATTN_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->set_attention_status(p_slot, 1); + wait_for_ctrl_irq (ctrl); + } - if (PWR_LED(ctrl->ctrlcap)) + if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_off(p_slot); + wait_for_ctrl_irq (ctrl); + } + + /* Done with exclusive hardware access */ + mutex_unlock(&ctrl->ctrl_lock); } } /***********SURPRISE REMOVAL********************/ @@ -642,6 +754,7 @@ static void interrupt_event_handler(struct controller *ctrl) } } + int pciehp_enable_slot(struct slot *p_slot) { u8 getstatus = 0; diff --git a/trunk/drivers/pci/hotplug/pciehp_hpc.c b/trunk/drivers/pci/hotplug/pciehp_hpc.c index fbc64aa2dd68..25d3aadfddbf 100644 --- a/trunk/drivers/pci/hotplug/pciehp_hpc.c +++ b/trunk/drivers/pci/hotplug/pciehp_hpc.c @@ -35,7 +35,6 @@ #include #include #include -#include #include "../pci.h" #include "pciehp.h" @@ -106,30 +105,34 @@ enum ctrl_offsets { ROOTCTRL = offsetof(struct ctrl_reg, root_ctrl), ROOTSTATUS = offsetof(struct ctrl_reg, root_status), }; - -static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) -{ - struct pci_dev *dev = ctrl->pci_dev; - return pci_read_config_word(dev, ctrl->cap_base + reg, value); -} - -static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) -{ - struct pci_dev *dev = ctrl->pci_dev; - return pci_read_config_dword(dev, ctrl->cap_base + reg, value); -} - -static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) -{ - struct pci_dev *dev = ctrl->pci_dev; - return pci_write_config_word(dev, ctrl->cap_base + reg, value); -} - -static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) -{ - struct pci_dev *dev = ctrl->pci_dev; - return pci_write_config_dword(dev, ctrl->cap_base + reg, value); -} +static int pcie_cap_base = 0; /* Base of the PCI Express capability item structure */ + +#define PCIE_CAP_ID(cb) ( cb + PCIECAPID ) +#define NXT_CAP_PTR(cb) ( cb + NXTCAPPTR ) +#define CAP_REG(cb) ( cb + CAPREG ) +#define DEV_CAP(cb) ( cb + DEVCAP ) +#define DEV_CTRL(cb) ( cb + DEVCTRL ) +#define DEV_STATUS(cb) ( cb + DEVSTATUS ) +#define LNK_CAP(cb) ( cb + LNKCAP ) +#define LNK_CTRL(cb) ( cb + LNKCTRL ) +#define LNK_STATUS(cb) ( cb + LNKSTATUS ) +#define SLOT_CAP(cb) ( cb + SLOTCAP ) +#define SLOT_CTRL(cb) ( cb + SLOTCTRL ) +#define SLOT_STATUS(cb) ( cb + SLOTSTATUS ) +#define ROOT_CTRL(cb) ( cb + ROOTCTRL ) +#define ROOT_STATUS(cb) ( cb + ROOTSTATUS ) + +#define hp_register_read_word(pdev, reg , value) \ + pci_read_config_word(pdev, reg, &value) + +#define hp_register_read_dword(pdev, reg , value) \ + pci_read_config_dword(pdev, reg, &value) + +#define hp_register_write_word(pdev, reg , value) \ + pci_write_config_word(pdev, reg, value) + +#define hp_register_dwrite_word(pdev, reg , value) \ + pci_write_config_dword(pdev, reg, value) /* Field definitions in PCI Express Capabilities Register */ #define CAP_VER 0x000F @@ -193,7 +196,6 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) #define ATTN_LED_CTRL 0x00C0 #define PWR_LED_CTRL 0x0300 #define PWR_CTRL 0x0400 -#define EMI_CTRL 0x0800 /* Attention indicator and Power indicator states */ #define LED_ON 0x01 @@ -204,10 +206,6 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) #define POWER_ON 0 #define POWER_OFF 0x0400 -/* EMI Status defines */ -#define EMI_DISENGAGED 0 -#define EMI_ENGAGED 1 - /* Field definitions in Slot Status Register */ #define ATTN_BUTTN_PRESSED 0x0001 #define PWR_FAULT_DETECTED 0x0002 @@ -216,117 +214,114 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) #define CMD_COMPLETED 0x0010 #define MRL_STATE 0x0020 #define PRSN_STATE 0x0040 -#define EMI_STATE 0x0080 -#define EMI_STATUS_BIT 7 static spinlock_t hpc_event_lock; DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ +static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ static int ctlr_seq_num = 0; /* Controller sequence # */ +static spinlock_t list_lock; + +static irqreturn_t pcie_isr(int IRQ, void *dev_id); -static irqreturn_t pcie_isr(int irq, void *dev_id); -static void start_int_poll_timer(struct controller *ctrl, int sec); +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); /* This is the interrupt polling timeout function. */ -static void int_poll_timeout(unsigned long data) +static void int_poll_timeout(unsigned long lphp_ctlr) { - struct controller *ctrl = (struct controller *)data; + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr; DBG_ENTER_ROUTINE + if ( !php_ctlr ) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return; + } + /* Poll for interrupt events. regs == NULL => polling */ - pcie_isr(0, ctrl); + pcie_isr( 0, (void *)php_ctlr ); + + init_timer(&php_ctlr->int_poll_timer); - init_timer(&ctrl->poll_timer); if (!pciehp_poll_time) pciehp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/ - start_int_poll_timer(ctrl, pciehp_poll_time); + start_int_poll_timer(php_ctlr, pciehp_poll_time); + + return; } /* This function starts the interrupt polling timer. */ -static void start_int_poll_timer(struct controller *ctrl, int sec) +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) { - /* Clamp to sane value */ - if ((sec <= 0) || (sec > 60)) - sec = 2; - - ctrl->poll_timer.function = &int_poll_timeout; - ctrl->poll_timer.data = (unsigned long)ctrl; - ctrl->poll_timer.expires = jiffies + sec * HZ; - add_timer(&ctrl->poll_timer); -} + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return; + } -static inline int pcie_wait_cmd(struct controller *ctrl) -{ - int retval = 0; - unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; - unsigned long timeout = msecs_to_jiffies(msecs); - int rc; + if ( ( seconds <= 0 ) || ( seconds > 60 ) ) + seconds = 2; /* Clamp to sane value */ - rc = wait_event_interruptible_timeout(ctrl->queue, - !ctrl->cmd_busy, timeout); - if (!rc) - dbg("Command not completed in 1000 msec\n"); - else if (rc < 0) { - retval = -EINTR; - info("Command was interrupted by a signal\n"); - } + php_ctlr->int_poll_timer.function = &int_poll_timeout; + php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; /* Instance data */ + php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ; + add_timer(&php_ctlr->int_poll_timer); - return retval; + return; } static int pcie_write_cmd(struct slot *slot, u16 cmd) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; int retval = 0; u16 slot_status; DBG_ENTER_ROUTINE - - mutex_lock(&ctrl->ctrl_lock); - - retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); - if (retval) { - err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); - goto out; + + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; } + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); + if (retval) { + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); + return retval; + } + if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { - /* After 1 sec and CMD_COMPLETED still not set, just - proceed forward to issue the next command according - to spec. Just print out the error message */ - dbg("%s: CMD_COMPLETED not clear after 1 sec.\n", - __FUNCTION__); + /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue + the next command according to spec. Just print out the error message */ + dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); } - ctrl->cmd_busy = 1; - retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE)); + retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE); if (retval) { - err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); - goto out; + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); + return retval; } - /* - * Wait for command completion. - */ - retval = pcie_wait_cmd(ctrl); - out: - mutex_unlock(&ctrl->ctrl_lock); DBG_LEAVE_ROUTINE return retval; } static int hpc_check_lnk_status(struct controller *ctrl) { + struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; u16 lnk_status; int retval = 0; DBG_ENTER_ROUTINE - retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(ctrl->cap_base), lnk_status); + if (retval) { - err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__); + err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); return retval; } @@ -345,21 +340,26 @@ static int hpc_check_lnk_status(struct controller *ctrl) static int hpc_get_attention_status(struct slot *slot, u8 *status) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_ctrl; u8 atten_led_state; int retval = 0; DBG_ENTER_ROUTINE - retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); + if (retval) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return retval; } - dbg("%s: SLOTCTRL %x, value read %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); + dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6; @@ -385,22 +385,27 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) return 0; } -static int hpc_get_power_status(struct slot *slot, u8 *status) +static int hpc_get_power_status(struct slot * slot, u8 *status) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_ctrl; u8 pwr_state; int retval = 0; DBG_ENTER_ROUTINE - retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); + if (retval) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return retval; } - dbg("%s: SLOTCTRL %x value read %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); + dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); pwr_state = (slot_ctrl & PWR_CTRL) >> 10; @@ -423,15 +428,21 @@ static int hpc_get_power_status(struct slot *slot, u8 *status) static int hpc_get_latch_status(struct slot *slot, u8 *status) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_status; int retval = 0; DBG_ENTER_ROUTINE - retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); + if (retval) { - err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return retval; } @@ -443,16 +454,22 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status) static int hpc_get_adapter_status(struct slot *slot, u8 *status) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_status; u8 card_state; int retval = 0; DBG_ENTER_ROUTINE - retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); + if (retval) { - err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return retval; } card_state = (u8)((slot_status & PRSN_STATE) >> 6); @@ -462,83 +479,54 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status) return 0; } -static int hpc_query_power_fault(struct slot *slot) +static int hpc_query_power_fault(struct slot * slot) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_status; u8 pwr_fault; int retval = 0; DBG_ENTER_ROUTINE - retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); - if (retval) { - err("%s: Cannot check for power fault\n", __FUNCTION__); - return retval; + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; } - pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); - - DBG_LEAVE_ROUTINE - return pwr_fault; -} -static int hpc_get_emi_status(struct slot *slot, u8 *status) -{ - struct controller *ctrl = slot->ctrl; - u16 slot_status; - int retval = 0; + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status); - DBG_ENTER_ROUTINE - - retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); if (retval) { - err("%s : Cannot check EMI status\n", __FUNCTION__); + err("%s : Cannot check for power fault\n", __FUNCTION__); return retval; } - *status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT; - + pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); + DBG_LEAVE_ROUTINE - return retval; + return pwr_fault; } -static int hpc_toggle_emi(struct slot *slot) +static int hpc_set_attention_status(struct slot *slot, u8 value) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd = 0; u16 slot_ctrl; int rc = 0; DBG_ENTER_ROUTINE - rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); - if (rc) { - err("%s : hp_register_read_word SLOT_CTRL failed\n", - __FUNCTION__); - return rc; + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; } - slot_cmd = (slot_ctrl | EMI_CTRL); - if (!pciehp_poll_mode) - slot_cmd = slot_cmd | HP_INTR_ENABLE; - - pcie_write_cmd(slot, slot_cmd); - slot->last_emi_toggle = get_seconds(); - DBG_LEAVE_ROUTINE - return rc; -} - -static int hpc_set_attention_status(struct slot *slot, u8 value) -{ - struct controller *ctrl = slot->ctrl; - u16 slot_cmd = 0; - u16 slot_ctrl; - int rc = 0; - - DBG_ENTER_ROUTINE + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); - rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return rc; } @@ -559,8 +547,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) slot_cmd = slot_cmd | HP_INTR_ENABLE; pcie_write_cmd(slot, slot_cmd); - dbg("%s: SLOTCTRL %x write cmd %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); + dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return rc; @@ -569,16 +556,27 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) static void hpc_set_green_led_on(struct slot *slot) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int rc = 0; DBG_ENTER_ROUTINE - rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return ; + } + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); + if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; @@ -587,24 +585,34 @@ static void hpc_set_green_led_on(struct slot *slot) pcie_write_cmd(slot, slot_cmd); - dbg("%s: SLOTCTRL %x write cmd %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); + dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return; } static void hpc_set_green_led_off(struct slot *slot) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int rc = 0; DBG_ENTER_ROUTINE - rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return ; + } + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); + if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } @@ -613,8 +621,7 @@ static void hpc_set_green_led_off(struct slot *slot) if (!pciehp_poll_mode) slot_cmd = slot_cmd | HP_INTR_ENABLE; pcie_write_cmd(slot, slot_cmd); - dbg("%s: SLOTCTRL %x write cmd %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); + dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return; @@ -622,16 +629,27 @@ static void hpc_set_green_led_off(struct slot *slot) static void hpc_set_green_led_blink(struct slot *slot) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; int rc = 0; DBG_ENTER_ROUTINE - rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return ; + } + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); + if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return; } @@ -641,54 +659,126 @@ static void hpc_set_green_led_blink(struct slot *slot) slot_cmd = slot_cmd | HP_INTR_ENABLE; pcie_write_cmd(slot, slot_cmd); - dbg("%s: SLOTCTRL %x write cmd %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); + dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return; } +int pcie_get_ctlr_slot_config(struct controller *ctrl, + int *num_ctlr_slots, /* number of slots in this HPC; only 1 in PCIE */ + int *first_device_num, /* PCI dev num of the first slot in this PCIE */ + int *physical_slot_num, /* phy slot num of the first slot in this PCIE */ + u8 *ctrlcap) +{ + struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; + u32 slot_cap; + int rc = 0; + + DBG_ENTER_ROUTINE + + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + *first_device_num = 0; + *num_ctlr_slots = 1; + + rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap); + + if (rc) { + err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__); + return -1; + } + + *physical_slot_num = slot_cap >> 19; + dbg("%s: PSN %d \n", __FUNCTION__, *physical_slot_num); + + *ctrlcap = slot_cap & 0x0000007f; + + DBG_LEAVE_ROUTINE + return 0; +} + static void hpc_release_ctlr(struct controller *ctrl) { + struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *p, *p_prev; + DBG_ENTER_ROUTINE - if (pciehp_poll_mode) - del_timer(&ctrl->poll_timer); - else - free_irq(ctrl->pci_dev->irq, ctrl); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (pciehp_poll_mode) { + del_timer(&php_ctlr->int_poll_timer); + } else { + if (php_ctlr->irq) { + free_irq(php_ctlr->irq, ctrl); + php_ctlr->irq = 0; + } + } + if (php_ctlr->pci_dev) + php_ctlr->pci_dev = NULL; + + spin_lock(&list_lock); + p = php_ctlr_list_head; + p_prev = NULL; + while (p) { + if (p == php_ctlr) { + if (p_prev) + p_prev->pnext = p->pnext; + else + php_ctlr_list_head = p->pnext; + break; + } else { + p_prev = p; + p = p->pnext; + } + } + spin_unlock(&list_lock); + + kfree(php_ctlr); DBG_LEAVE_ROUTINE + } static int hpc_power_on_slot(struct slot * slot) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl, slot_status; + int retval = 0; DBG_ENTER_ROUTINE + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } /* Clear sticky power-fault bit from previous power failures */ - retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); - if (retval) { - err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); - return retval; - } + hp_register_read_word(php_ctlr->pci_dev, + SLOT_STATUS(slot->ctrl->cap_base), slot_status); slot_status &= PWR_FAULT_DETECTED; - if (slot_status) { - retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status); - if (retval) { - err("%s: Cannot write to SLOTSTATUS register\n", - __FUNCTION__); - return retval; - } - } + if (slot_status) + hp_register_write_word(php_ctlr->pci_dev, + SLOT_STATUS(slot->ctrl->cap_base), slot_status); + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); - retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); if (retval) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return retval; } @@ -708,8 +798,7 @@ static int hpc_power_on_slot(struct slot * slot) err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); return -1; } - dbg("%s: SLOTCTRL %x write cmd %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); + dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE @@ -718,18 +807,29 @@ static int hpc_power_on_slot(struct slot * slot) static int hpc_power_off_slot(struct slot * slot) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; u16 slot_cmd; u16 slot_ctrl; + int retval = 0; DBG_ENTER_ROUTINE + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); + slot->hp_slot = 0; + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl); - retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); if (retval) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return retval; } @@ -754,25 +854,47 @@ static int hpc_power_off_slot(struct slot * slot) err("%s: Write command failed!\n", __FUNCTION__); return -1; } - dbg("%s: SLOTCTRL %x write cmd %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); + dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd); DBG_LEAVE_ROUTINE return retval; } -static irqreturn_t pcie_isr(int irq, void *dev_id) +static irqreturn_t pcie_isr(int IRQ, void *dev_id) { - struct controller *ctrl = (struct controller *)dev_id; + struct controller *ctrl = NULL; + struct php_ctlr_state_s *php_ctlr; + u8 schedule_flag = 0; u16 slot_status, intr_detect, intr_loc; u16 temp_word; int hp_slot = 0; /* only 1 slot per PCI Express port */ int rc = 0; - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); + if (!dev_id) + return IRQ_NONE; + + if (!pciehp_poll_mode) { + ctrl = dev_id; + php_ctlr = ctrl->hpc_ctlr_handle; + } else { + php_ctlr = dev_id; + ctrl = (struct controller *)php_ctlr->callback_instance_id; + } + + if (!ctrl) { + dbg("%s: dev_id %p ctlr == NULL\n", __FUNCTION__, (void*) dev_id); + return IRQ_NONE; + } + + if (!php_ctlr) { + dbg("%s: php_ctlr == NULL\n", __FUNCTION__); + return IRQ_NONE; + } + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { - err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } @@ -788,38 +910,33 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); /* Mask Hot-plug Interrupt Enable */ if (!pciehp_poll_mode) { - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot read SLOT_CTRL register\n", - __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } - dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n", - __FUNCTION__, temp_word); + dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word); temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); + + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot write to SLOTCTRL register\n", - __FUNCTION__); + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } - - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { - err("%s: Cannot read SLOT_STATUS register\n", - __FUNCTION__); + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } - dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n", - __FUNCTION__, slot_status); + dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); /* Clear command complete interrupt caused by this write */ temp_word = 0x1f; - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot write to SLOTSTATUS register\n", - __FUNCTION__); + err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } } @@ -828,65 +945,60 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) /* * Command Complete Interrupt Pending */ - ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } - if (intr_loc & MRL_SENS_CHANGED) - pciehp_handle_switch_change(hp_slot, ctrl); - - if (intr_loc & ATTN_BUTTN_PRESSED) - pciehp_handle_attention_button(hp_slot, ctrl); - - if (intr_loc & PRSN_DETECT_CHANGED) - pciehp_handle_presence_change(hp_slot, ctrl); - - if (intr_loc & PWR_FAULT_DETECTED) - pciehp_handle_power_fault(hp_slot, ctrl); + if ((php_ctlr->switch_change_callback) && (intr_loc & MRL_SENS_CHANGED)) + schedule_flag += php_ctlr->switch_change_callback( + hp_slot, php_ctlr->callback_instance_id); + if ((php_ctlr->attention_button_callback) && (intr_loc & ATTN_BUTTN_PRESSED)) + schedule_flag += php_ctlr->attention_button_callback( + hp_slot, php_ctlr->callback_instance_id); + if ((php_ctlr->presence_change_callback) && (intr_loc & PRSN_DETECT_CHANGED)) + schedule_flag += php_ctlr->presence_change_callback( + hp_slot , php_ctlr->callback_instance_id); + if ((php_ctlr->power_fault_callback) && (intr_loc & PWR_FAULT_DETECTED)) + schedule_flag += php_ctlr->power_fault_callback( + hp_slot, php_ctlr->callback_instance_id); /* Clear all events after serving them */ temp_word = 0x1F; - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); + err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } /* Unmask Hot-plug Interrupt Enable */ if (!pciehp_poll_mode) { - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot read SLOTCTRL register\n", - __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot write to SLOTCTRL register\n", - __FUNCTION__); + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); return IRQ_NONE; } - - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { - err("%s: Cannot read SLOT_STATUS register\n", - __FUNCTION__); + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } /* Clear command complete interrupt caused by this write */ temp_word = 0x1F; - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot write to SLOTSTATUS failed\n", - __FUNCTION__); + err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); return IRQ_NONE; } - dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n", - __FUNCTION__, temp_word); + dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); } return IRQ_HANDLED; @@ -894,16 +1006,27 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_speed lnk_speed; u32 lnk_cap; int retval = 0; DBG_ENTER_ROUTINE - retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap); + if (retval) { - err("%s: Cannot read LNKCAP register\n", __FUNCTION__); + err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__); return retval; } @@ -924,16 +1047,27 @@ static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value) static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_width lnk_wdth; u32 lnk_cap; int retval = 0; DBG_ENTER_ROUTINE - retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap); + if (retval) { - err("%s: Cannot read LNKCAP register\n", __FUNCTION__); + err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__); return retval; } @@ -975,16 +1109,27 @@ static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN; int retval = 0; u16 lnk_status; DBG_ENTER_ROUTINE - retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status); + if (retval) { - err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__); + err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); return retval; } @@ -1005,16 +1150,27 @@ static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value) static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value) { - struct controller *ctrl = slot->ctrl; + struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN; int retval = 0; u16 lnk_status; DBG_ENTER_ROUTINE - retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status); + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status); + if (retval) { - err("%s: Cannot read LNKSTATUS register\n", __FUNCTION__); + err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); return retval; } @@ -1062,8 +1218,6 @@ static struct hpc_ops pciehp_hpc_ops = { .get_attention_status = hpc_get_attention_status, .get_latch_status = hpc_get_latch_status, .get_adapter_status = hpc_get_adapter_status, - .get_emi_status = hpc_get_emi_status, - .toggle_emi = hpc_toggle_emi, .get_max_bus_speed = hpc_get_max_lnk_speed, .get_cur_bus_speed = hpc_get_cur_lnk_speed, @@ -1151,24 +1305,38 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) int pcie_init(struct controller * ctrl, struct pcie_device *dev) { + struct php_ctlr_state_s *php_ctlr, *p; + void *instance_id = ctrl; int rc; static int first = 1; u16 temp_word; u16 cap_reg; u16 intr_enable = 0; u32 slot_cap; - int cap_base; + int cap_base, saved_cap_base; u16 slot_status, slot_ctrl; struct pci_dev *pdev; DBG_ENTER_ROUTINE + spin_lock_init(&list_lock); + php_ctlr = kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); + + if (!php_ctlr) { /* allocate controller state data */ + err("%s: HPC controller memory allocation error!\n", __FUNCTION__); + goto abort; + } + + memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s)); + pdev = dev->port; - ctrl->pci_dev = pdev; /* save pci_dev in context */ + php_ctlr->pci_dev = pdev; /* save pci_dev in context */ dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n", __FUNCTION__, pdev->vendor, pdev->device); + saved_cap_base = pcie_cap_base; + if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) { dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__); goto abort_free_ctlr; @@ -1176,15 +1344,14 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) ctrl->cap_base = cap_base; - dbg("%s: pcie_cap_base %x\n", __FUNCTION__, cap_base); + dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base); - rc = pciehp_readw(ctrl, CAPREG, &cap_reg); + rc = hp_register_read_word(pdev, CAP_REG(ctrl->cap_base), cap_reg); if (rc) { - err("%s: Cannot read CAPREG register\n", __FUNCTION__); + err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: CAPREG offset %x cap_reg %x\n", - __FUNCTION__, ctrl->cap_base + CAPREG, cap_reg); + dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG(ctrl->cap_base), cap_reg); if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 0x0040) && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) { @@ -1192,34 +1359,31 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) goto abort_free_ctlr; } - rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap); + rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap); if (rc) { - err("%s: Cannot read SLOTCAP register\n", __FUNCTION__); + err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: SLOTCAP offset %x slot_cap %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap); + dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP(ctrl->cap_base), slot_cap); if (!(slot_cap & HP_CAP)) { dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__); goto abort_free_ctlr; } /* For debugging purpose */ - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { - err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: SLOTSTATUS offset %x slot_status %x\n", - __FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status); + dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), slot_status); - rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), slot_ctrl); if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); + dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), slot_ctrl); if (first) { spin_lock_init(&hpc_event_lock); @@ -1241,64 +1405,69 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) /* setup wait queue */ init_waitqueue_head(&ctrl->queue); + /* find the IRQ */ + php_ctlr->irq = dev->irq; + + /* Save interrupt callback info */ + php_ctlr->attention_button_callback = pciehp_handle_attention_button; + php_ctlr->switch_change_callback = pciehp_handle_switch_change; + php_ctlr->presence_change_callback = pciehp_handle_presence_change; + php_ctlr->power_fault_callback = pciehp_handle_power_fault; + php_ctlr->callback_instance_id = instance_id; + /* return PCI Controller Info */ - ctrl->slot_device_offset = 0; - ctrl->num_slots = 1; - ctrl->first_slot = slot_cap >> 19; - ctrl->ctrlcap = slot_cap & 0x0000007f; + php_ctlr->slot_device_offset = 0; + php_ctlr->num_slots = 1; /* Mask Hot-plug Interrupt Enable */ - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); + rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); goto abort_free_ctlr; } - dbg("%s: SLOTCTRL %x value read %x\n", - __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word); + dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word); temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); + rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); goto abort_free_ctlr; } - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { - err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); goto abort_free_ctlr; } temp_word = 0x1F; /* Clear all events */ - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); + err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); goto abort_free_ctlr; } - if (pciehp_poll_mode) { - /* Install interrupt polling timer. Start with 10 sec delay */ - init_timer(&ctrl->poll_timer); - start_int_poll_timer(ctrl, 10); + if (pciehp_poll_mode) {/* Install interrupt polling code */ + /* Install and start the interrupt polling timer */ + init_timer(&php_ctlr->int_poll_timer); + start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ } else { /* Installs the interrupt handler */ - rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED, - MY_NAME, (void *)ctrl); - dbg("%s: request_irq %d for hpc%d (returns %d)\n", - __FUNCTION__, ctrl->pci_dev->irq, ctlr_seq_num, rc); + rc = request_irq(php_ctlr->irq, pcie_isr, IRQF_SHARED, MY_NAME, (void *) ctrl); + dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); if (rc) { - err("Can't get irq %d for the hotplug controller\n", - ctrl->pci_dev->irq); + err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq); goto abort_free_ctlr; } } + dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); + rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); goto abort_free_irq; } @@ -1322,21 +1491,21 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) } /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); + rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); goto abort_free_irq; } - rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status); if (rc) { - err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); goto abort_disable_intr; } temp_word = 0x1F; /* Clear all events */ - rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word); if (rc) { - err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); + err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); goto abort_disable_intr; } @@ -1349,7 +1518,24 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) goto abort_disable_intr; } + /* Add this HPC instance into the HPC list */ + spin_lock(&list_lock); + if (php_ctlr_list_head == 0) { + php_ctlr_list_head = php_ctlr; + p = php_ctlr_list_head; + p->pnext = NULL; + } else { + p = php_ctlr_list_head; + + while (p->pnext) + p = p->pnext; + + p->pnext = php_ctlr; + } + spin_unlock(&list_lock); + ctlr_seq_num++; + ctrl->hpc_ctlr_handle = php_ctlr; ctrl->hpc_ops = &pciehp_hpc_ops; DBG_LEAVE_ROUTINE @@ -1357,21 +1543,24 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) /* We end up here for the many possible ways to fail this API. */ abort_disable_intr: - rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); + rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); if (!rc) { temp_word &= ~(intr_enable | HP_INTR_ENABLE); - rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); + rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word); } if (rc) err("%s : disabling interrupts failed\n", __FUNCTION__); abort_free_irq: if (pciehp_poll_mode) - del_timer_sync(&ctrl->poll_timer); + del_timer_sync(&php_ctlr->int_poll_timer); else - free_irq(ctrl->pci_dev->irq, ctrl); + free_irq(php_ctlr->irq, ctrl); abort_free_ctlr: + pcie_cap_base = saved_cap_base; + kfree(php_ctlr); +abort: DBG_LEAVE_ROUTINE return -1; } diff --git a/trunk/drivers/pci/hotplug/shpchp.h b/trunk/drivers/pci/hotplug/shpchp.h index 01d31a1f697c..3ca6a4f574b3 100644 --- a/trunk/drivers/pci/hotplug/shpchp.h +++ b/trunk/drivers/pci/hotplug/shpchp.h @@ -106,7 +106,7 @@ struct controller { }; /* Define AMD SHPC ID */ -#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 +#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 /* AMD PCIX bridge registers */ @@ -221,7 +221,7 @@ enum ctrl_offsets { }; static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot) -{ +{ return hotplug_slot->private; } diff --git a/trunk/drivers/pci/hotplug/shpchp_core.c b/trunk/drivers/pci/hotplug/shpchp_core.c index 5f4bc08a633a..590cd3cbe010 100644 --- a/trunk/drivers/pci/hotplug/shpchp_core.c +++ b/trunk/drivers/pci/hotplug/shpchp_core.c @@ -401,6 +401,10 @@ static int __init shpcd_init(void) { int retval = 0; +#ifdef CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE + shpchp_poll_mode = 1; +#endif + retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); diff --git a/trunk/drivers/pci/hotplug/shpchp_ctrl.c b/trunk/drivers/pci/hotplug/shpchp_ctrl.c index b746bd265bc6..6bb84734cd6c 100644 --- a/trunk/drivers/pci/hotplug/shpchp_ctrl.c +++ b/trunk/drivers/pci/hotplug/shpchp_ctrl.c @@ -64,7 +64,7 @@ u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl) /* Attention Button Change */ dbg("shpchp: Attention button interrupt received.\n"); - + p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); @@ -128,7 +128,7 @@ u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl) p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); - /* + /* * Save the presence state */ p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save)); @@ -184,12 +184,12 @@ u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl) return 1; } -/* The following routines constitute the bulk of the +/* The following routines constitute the bulk of the hotplug controller logic */ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, enum pci_bus_speed speed) -{ +{ int rc = 0; dbg("%s: change to speed %d\n", __FUNCTION__, speed); @@ -204,7 +204,7 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot, static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp, enum pci_bus_speed msp) -{ +{ int rc = 0; /* @@ -257,23 +257,23 @@ static int board_added(struct slot *p_slot) err("%s: Failed to power on slot\n", __FUNCTION__); return -1; } - + if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) { if (slots_not_empty) return WRONG_BUS_FREQUENCY; - + if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) { err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); return WRONG_BUS_FREQUENCY; } - + /* turn on board, blink green LED, turn off Amber LED */ if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) { err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); return rc; } } - + rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp); if (rc) { err("%s: Can't get adapter speed or bus mode mismatch\n", @@ -378,7 +378,7 @@ static int remove_board(struct slot *p_slot) err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); return rc; } - + rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); if (rc) { err("%s: Issue of Set Attention command failed\n", __FUNCTION__); diff --git a/trunk/drivers/pci/hotplug/shpchp_hpc.c b/trunk/drivers/pci/hotplug/shpchp_hpc.c index 5183a45d45b5..b7bede4b7c27 100644 --- a/trunk/drivers/pci/hotplug/shpchp_hpc.c +++ b/trunk/drivers/pci/hotplug/shpchp_hpc.c @@ -35,6 +35,38 @@ #include "shpchp.h" +#ifdef DEBUG +#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ +#define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ +#define DBG_K_INFO ((unsigned int)0x00000004) /* Info messages */ +#define DBG_K_ERROR ((unsigned int)0x00000008) /* Error messages */ +#define DBG_K_TRACE (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT) +#define DBG_K_STANDARD (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE) +/* Redefine this flagword to set debug level */ +#define DEBUG_LEVEL DBG_K_STANDARD + +#define DEFINE_DBG_BUFFER char __dbg_str_buf[256]; + +#define DBG_PRINT( dbg_flags, args... ) \ + do { \ + if ( DEBUG_LEVEL & ( dbg_flags ) ) \ + { \ + int len; \ + len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \ + __FILE__, __LINE__, __FUNCTION__ ); \ + sprintf( __dbg_str_buf + len, args ); \ + printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \ + } \ + } while (0) + +#define DBG_ENTER_ROUTINE DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]"); +#define DBG_LEAVE_ROUTINE DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]"); +#else +#define DEFINE_DBG_BUFFER +#define DBG_ENTER_ROUTINE +#define DBG_LEAVE_ROUTINE +#endif /* DEBUG */ + /* Slot Available Register I field definition */ #define SLOT_33MHZ 0x0000001f #define SLOT_66MHZ_PCIX 0x00001f00 @@ -179,6 +211,7 @@ #define SLOT_EVENT_LATCH 0x2 #define SLOT_SERR_INT_MASK 0x3 +DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); static irqreturn_t shpc_isr(int irq, void *dev_id); @@ -235,6 +268,8 @@ static void int_poll_timeout(unsigned long data) { struct controller *ctrl = (struct controller *)data; + DBG_ENTER_ROUTINE + /* Poll for interrupt events. regs == NULL => polling */ shpc_isr(0, ctrl); @@ -243,6 +278,8 @@ static void int_poll_timeout(unsigned long data) shpchp_poll_time = 2; /* default polling interval is 2 sec */ start_int_poll_timer(ctrl, shpchp_poll_time); + + DBG_LEAVE_ROUTINE } /* @@ -316,6 +353,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) int retval = 0; u16 temp_word; + DBG_ENTER_ROUTINE + mutex_lock(&slot->ctrl->cmd_lock); if (!shpc_poll_ctrl_busy(ctrl)) { @@ -329,9 +368,9 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) ++t_slot; temp_word = (t_slot << 8) | (cmd & 0xFF); dbg("%s: t_slot %x cmd %x\n", __FUNCTION__, t_slot, cmd); - + /* To make sure the Controller Busy bit is 0 before we send out the - * command. + * command. */ shpc_writew(ctrl, CMD, temp_word); @@ -350,14 +389,20 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) } out: mutex_unlock(&slot->ctrl->cmd_lock); + + DBG_LEAVE_ROUTINE return retval; } static int hpc_check_cmd_status(struct controller *ctrl) { + u16 cmd_status; int retval = 0; - u16 cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; + DBG_ENTER_ROUTINE + + cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; + switch (cmd_status >> 1) { case 0: retval = 0; @@ -378,6 +423,7 @@ static int hpc_check_cmd_status(struct controller *ctrl) retval = cmd_status; } + DBG_LEAVE_ROUTINE return retval; } @@ -385,8 +431,13 @@ static int hpc_check_cmd_status(struct controller *ctrl) static int hpc_get_attention_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; - u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - u8 state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; + u32 slot_reg; + u8 state; + + DBG_ENTER_ROUTINE + + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; switch (state) { case ATN_LED_STATE_ON: @@ -403,14 +454,20 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status) break; } + DBG_LEAVE_ROUTINE return 0; } static int hpc_get_power_status(struct slot * slot, u8 *status) { struct controller *ctrl = slot->ctrl; - u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - u8 state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; + u32 slot_reg; + u8 state; + + DBG_ENTER_ROUTINE + + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; switch (state) { case SLOT_STATE_PWRONLY: @@ -427,6 +484,7 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) break; } + DBG_LEAVE_ROUTINE return 0; } @@ -434,21 +492,30 @@ static int hpc_get_power_status(struct slot * slot, u8 *status) static int hpc_get_latch_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; - u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + u32 slot_reg; + + DBG_ENTER_ROUTINE + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ + DBG_LEAVE_ROUTINE return 0; } static int hpc_get_adapter_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; - u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); - u8 state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; + u32 slot_reg; + u8 state; + DBG_ENTER_ROUTINE + + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; *status = (state != 0x3) ? 1 : 0; + DBG_LEAVE_ROUTINE return 0; } @@ -456,8 +523,11 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) { struct controller *ctrl = slot->ctrl; + DBG_ENTER_ROUTINE + *prog_int = shpc_readb(ctrl, PROG_INTERFACE); + DBG_LEAVE_ROUTINE return 0; } @@ -469,6 +539,8 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) u8 m66_cap = !!(slot_reg & MHZ66_CAP); u8 pi, pcix_cap; + DBG_ENTER_ROUTINE + if ((retval = hpc_get_prog_int(slot, &pi))) return retval; @@ -510,15 +582,21 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) } dbg("Adapter speed = %d\n", *value); + DBG_LEAVE_ROUTINE return retval; } static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) { - int retval = 0; struct controller *ctrl = slot->ctrl; - u16 sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); - u8 pi = shpc_readb(ctrl, PROG_INTERFACE); + u16 sec_bus_status; + u8 pi; + int retval = 0; + + DBG_ENTER_ROUTINE + + pi = shpc_readb(ctrl, PROG_INTERFACE); + sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); if (pi == 2) { *mode = (sec_bus_status & 0x0100) >> 8; @@ -527,14 +605,21 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) } dbg("Mode 1 ECC cap = %d\n", *mode); + + DBG_LEAVE_ROUTINE return retval; } static int hpc_query_power_fault(struct slot * slot) { struct controller *ctrl = slot->ctrl; - u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + u32 slot_reg; + + DBG_ENTER_ROUTINE + + slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); + DBG_LEAVE_ROUTINE /* Note: Logic 0 => fault */ return !(slot_reg & POWER_FAULT); } @@ -544,7 +629,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value) u8 slot_cmd = 0; switch (value) { - case 0 : + case 0 : slot_cmd = SET_ATTN_OFF; /* OFF */ break; case 1: @@ -581,6 +666,8 @@ static void hpc_release_ctlr(struct controller *ctrl) int i; u32 slot_reg, serr_int; + DBG_ENTER_ROUTINE + /* * Mask event interrupts and SERRs of all slots */ @@ -621,43 +708,61 @@ static void hpc_release_ctlr(struct controller *ctrl) */ if (atomic_dec_and_test(&shpchp_num_controllers)) destroy_workqueue(shpchp_wq); + + DBG_LEAVE_ROUTINE } static int hpc_power_on_slot(struct slot * slot) { int retval; + DBG_ENTER_ROUTINE + retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR); - if (retval) + if (retval) { err("%s: Write command failed!\n", __FUNCTION__); + return retval; + } - return retval; + DBG_LEAVE_ROUTINE + + return 0; } static int hpc_slot_enable(struct slot * slot) { int retval; + DBG_ENTER_ROUTINE + /* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF); - if (retval) + if (retval) { err("%s: Write command failed!\n", __FUNCTION__); + return retval; + } - return retval; + DBG_LEAVE_ROUTINE + return 0; } static int hpc_slot_disable(struct slot * slot) { int retval; + DBG_ENTER_ROUTINE + /* Slot - Disable, Power Indicator - Off, Attention Indicator - On */ retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON); - if (retval) + if (retval) { err("%s: Write command failed!\n", __FUNCTION__); + return retval; + } - return retval; + DBG_LEAVE_ROUTINE + return 0; } static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) @@ -666,6 +771,8 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) struct controller *ctrl = slot->ctrl; u8 pi, cmd; + DBG_ENTER_ROUTINE + pi = shpc_readb(ctrl, PROG_INTERFACE); if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) return -EINVAL; @@ -721,6 +828,7 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) if (retval) err("%s: Write command failed!\n", __FUNCTION__); + DBG_LEAVE_ROUTINE return retval; } @@ -735,7 +843,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) if (!intr_loc) return IRQ_NONE; - dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); + dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); if(!shpchp_poll_mode) { /* @@ -748,12 +856,12 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); intr_loc2 = shpc_readl(ctrl, INTR_LOC); - dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); + dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); } if (intr_loc & CMD_INTR_PENDING) { - /* - * Command Complete Interrupt Pending + /* + * Command Complete Interrupt Pending * RO only - clear by writing 1 to the Command Completion * Detect bit in Controller SERR-INT register */ @@ -767,7 +875,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) if (!(intr_loc & ~CMD_INTR_PENDING)) goto out; - for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { + for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { /* To find out which slot has interrupt pending */ if (!(intr_loc & SLOT_INTR_PENDING(hp_slot))) continue; @@ -799,7 +907,7 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); } - + return IRQ_HANDLED; } @@ -812,6 +920,8 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2); + DBG_ENTER_ROUTINE + if (pi == 2) { if (slot_avail2 & SLOT_133MHZ_PCIX_533) bus_speed = PCI_SPEED_133MHz_PCIX_533; @@ -844,7 +954,7 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) *value = bus_speed; dbg("Max bus speed = %d\n", bus_speed); - + DBG_LEAVE_ROUTINE return retval; } @@ -857,6 +967,8 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) u8 pi = shpc_readb(ctrl, PROG_INTERFACE); u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); + DBG_ENTER_ROUTINE + if ((pi == 1) && (speed_mode > 4)) { *value = PCI_SPEED_UNKNOWN; return -ENODEV; @@ -912,6 +1024,7 @@ static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) } dbg("Current bus speed = %d\n", bus_speed); + DBG_LEAVE_ROUTINE return retval; } @@ -919,7 +1032,7 @@ static struct hpc_ops shpchp_hpc_ops = { .power_on_slot = hpc_power_on_slot, .slot_enable = hpc_slot_enable, .slot_disable = hpc_slot_disable, - .set_bus_speed_mode = hpc_set_bus_speed_mode, + .set_bus_speed_mode = hpc_set_bus_speed_mode, .set_attention_status = hpc_set_attention_status, .get_power_status = hpc_get_power_status, .get_attention_status = hpc_get_attention_status, @@ -936,7 +1049,7 @@ static struct hpc_ops shpchp_hpc_ops = { .green_led_on = hpc_set_green_led_on, .green_led_off = hpc_set_green_led_off, .green_led_blink = hpc_set_green_led_blink, - + .release_ctlr = hpc_release_ctlr, }; @@ -948,6 +1061,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) u32 tempdword, slot_reg, slot_config; u8 i; + DBG_ENTER_ROUTINE + ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == @@ -993,9 +1108,9 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) ctrl->mmio_size = 0x24 + 0x4 * num_slots; } - info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, + info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); - + rc = pci_enable_device(pdev); if (rc) { err("%s: pci_enable_device failed\n", __FUNCTION__); @@ -1057,7 +1172,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) slot_reg &= ~SLOT_REG_RSVDZ_MASK; shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); } - + if (shpchp_poll_mode) { /* Install interrupt polling timer. Start with 10 sec delay */ init_timer(&ctrl->poll_timer); @@ -1069,7 +1184,7 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) info("Can't get msi for the hotplug controller\n"); info("Use INTx for the hotplug controller\n"); } - + rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, MY_NAME, (void *)ctrl); dbg("%s: request_irq %d for hpc%d (returns %d)\n", @@ -1120,11 +1235,13 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev) dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); } + DBG_LEAVE_ROUTINE return 0; /* We end up here for the many possible ways to fail this API. */ abort_iounmap: iounmap(ctrl->creg); abort: + DBG_LEAVE_ROUTINE return rc; } diff --git a/trunk/drivers/pci/msi.c b/trunk/drivers/pci/msi.c index 68555c11f556..ed3f7e1a563c 100644 --- a/trunk/drivers/pci/msi.c +++ b/trunk/drivers/pci/msi.c @@ -24,6 +24,8 @@ #include "pci.h" #include "msi.h" +static DEFINE_SPINLOCK(msi_lock); +static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; static struct kmem_cache* msi_cachep; static int pci_msi_enable = 1; @@ -42,13 +44,13 @@ static void msi_set_mask_bit(unsigned int irq, int flag) { struct msi_desc *entry; - entry = get_irq_msi(irq); + entry = msi_desc[irq]; BUG_ON(!entry || !entry->dev); switch (entry->msi_attrib.type) { case PCI_CAP_ID_MSI: if (entry->msi_attrib.maskbit) { - int pos; - u32 mask_bits; + int pos; + u32 mask_bits; pos = (long)entry->mask_base; pci_read_config_dword(entry->dev, pos, &mask_bits); @@ -72,7 +74,7 @@ static void msi_set_mask_bit(unsigned int irq, int flag) void read_msi_msg(unsigned int irq, struct msi_msg *msg) { - struct msi_desc *entry = get_irq_msi(irq); + struct msi_desc *entry = get_irq_data(irq); switch(entry->msi_attrib.type) { case PCI_CAP_ID_MSI: { @@ -111,7 +113,7 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) void write_msi_msg(unsigned int irq, struct msi_msg *msg) { - struct msi_desc *entry = get_irq_msi(irq); + struct msi_desc *entry = get_irq_data(irq); switch (entry->msi_attrib.type) { case PCI_CAP_ID_MSI: { @@ -160,7 +162,6 @@ void unmask_msi_irq(unsigned int irq) } static int msi_free_irq(struct pci_dev* dev, int irq); - static int msi_init(void) { static int status = -ENOMEM; @@ -168,6 +169,13 @@ static int msi_init(void) if (!status) return status; + if (pci_msi_quirk) { + pci_msi_enable = 0; + printk(KERN_WARNING "PCI: MSI quirk detected. MSI disabled.\n"); + status = -EINVAL; + return status; + } + status = msi_cache_init(); if (status < 0) { pci_msi_enable = 0; @@ -192,6 +200,46 @@ static struct msi_desc* alloc_msi_entry(void) return entry; } +static void attach_msi_entry(struct msi_desc *entry, int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&msi_lock, flags); + msi_desc[irq] = entry; + spin_unlock_irqrestore(&msi_lock, flags); +} + +static int create_msi_irq(void) +{ + struct msi_desc *entry; + int irq; + + entry = alloc_msi_entry(); + if (!entry) + return -ENOMEM; + + irq = create_irq(); + if (irq < 0) { + kmem_cache_free(msi_cachep, entry); + return -EBUSY; + } + + set_irq_data(irq, entry); + + return irq; +} + +static void destroy_msi_irq(unsigned int irq) +{ + struct msi_desc *entry; + + entry = get_irq_data(irq); + set_irq_chip(irq, NULL); + set_irq_data(irq, NULL); + destroy_irq(irq); + kmem_cache_free(msi_cachep, entry); +} + static void enable_msi_mode(struct pci_dev *dev, int pos, int type) { u16 control; @@ -230,8 +278,36 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type) pci_intx(dev, 1); /* enable intx */ } +static int msi_lookup_irq(struct pci_dev *dev, int type) +{ + int irq; + unsigned long flags; + + spin_lock_irqsave(&msi_lock, flags); + for (irq = 0; irq < NR_IRQS; irq++) { + if (!msi_desc[irq] || msi_desc[irq]->dev != dev || + msi_desc[irq]->msi_attrib.type != type || + msi_desc[irq]->msi_attrib.default_irq != dev->irq) + continue; + spin_unlock_irqrestore(&msi_lock, flags); + /* This pre-assigned MSI irq for this device + already exits. Override dev->irq with this irq */ + dev->irq = irq; + return 0; + } + spin_unlock_irqrestore(&msi_lock, flags); + + return -EACCES; +} + +void pci_scan_msi_device(struct pci_dev *dev) +{ + if (!dev) + return; +} + #ifdef CONFIG_PM -static int __pci_save_msi_state(struct pci_dev *dev) +int pci_save_msi_state(struct pci_dev *dev) { int pos, i = 0; u16 control; @@ -269,7 +345,7 @@ static int __pci_save_msi_state(struct pci_dev *dev) return 0; } -static void __pci_restore_msi_state(struct pci_dev *dev) +void pci_restore_msi_state(struct pci_dev *dev) { int i = 0, pos; u16 control; @@ -297,16 +373,14 @@ static void __pci_restore_msi_state(struct pci_dev *dev) kfree(save_state); } -static int __pci_save_msix_state(struct pci_dev *dev) +int pci_save_msix_state(struct pci_dev *dev) { int pos; + int temp; int irq, head, tail = 0; u16 control; struct pci_cap_saved_state *save_state; - if (!dev->msix_enabled) - return 0; - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); if (pos <= 0 || dev->no_msi) return 0; @@ -324,46 +398,38 @@ static int __pci_save_msix_state(struct pci_dev *dev) *((u16 *)&save_state->data[0]) = control; /* save the table */ - irq = head = dev->first_msi_irq; + temp = dev->irq; + if (msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { + kfree(save_state); + return -EINVAL; + } + + irq = head = dev->irq; while (head != tail) { struct msi_desc *entry; - entry = get_irq_msi(irq); + entry = msi_desc[irq]; read_msi_msg(irq, &entry->msg_save); - tail = entry->link.tail; + tail = msi_desc[irq]->link.tail; irq = tail; } + dev->irq = temp; save_state->cap_nr = PCI_CAP_ID_MSIX; pci_add_saved_cap(dev, save_state); return 0; } -int pci_save_msi_state(struct pci_dev *dev) -{ - int rc; - - rc = __pci_save_msi_state(dev); - if (rc) - return rc; - - rc = __pci_save_msix_state(dev); - - return rc; -} - -static void __pci_restore_msix_state(struct pci_dev *dev) +void pci_restore_msix_state(struct pci_dev *dev) { u16 save; int pos; int irq, head, tail = 0; struct msi_desc *entry; + int temp; struct pci_cap_saved_state *save_state; - if (!dev->msix_enabled) - return; - save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); if (!save_state) return; @@ -376,25 +442,23 @@ static void __pci_restore_msix_state(struct pci_dev *dev) return; /* route the table */ - irq = head = dev->first_msi_irq; + temp = dev->irq; + if (msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) + return; + irq = head = dev->irq; while (head != tail) { - entry = get_irq_msi(irq); + entry = msi_desc[irq]; write_msi_msg(irq, &entry->msg_save); - tail = entry->link.tail; + tail = msi_desc[irq]->link.tail; irq = tail; } + dev->irq = temp; pci_write_config_word(dev, msi_control_reg(pos), save); enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); } - -void pci_restore_msi_state(struct pci_dev *dev) -{ - __pci_restore_msi_state(dev); - __pci_restore_msix_state(dev); -} -#endif /* CONFIG_PM */ +#endif /** * msi_capability_init - configure device's MSI capability structure @@ -407,6 +471,7 @@ void pci_restore_msi_state(struct pci_dev *dev) **/ static int msi_capability_init(struct pci_dev *dev) { + int status; struct msi_desc *entry; int pos, irq; u16 control; @@ -414,10 +479,13 @@ static int msi_capability_init(struct pci_dev *dev) pos = pci_find_capability(dev, PCI_CAP_ID_MSI); pci_read_config_word(dev, msi_control_reg(pos), &control); /* MSI Entry Initialization */ - entry = alloc_msi_entry(); - if (!entry) - return -ENOMEM; + irq = create_msi_irq(); + if (irq < 0) + return irq; + entry = get_irq_data(irq); + entry->link.head = irq; + entry->link.tail = irq; entry->msi_attrib.type = PCI_CAP_ID_MSI; entry->msi_attrib.is_64 = is_64bit_address(control); entry->msi_attrib.entry_nr = 0; @@ -443,16 +511,13 @@ static int msi_capability_init(struct pci_dev *dev) maskbits); } /* Configure MSI capability structure */ - irq = arch_setup_msi_irq(dev, entry); - if (irq < 0) { - kmem_cache_free(msi_cachep, entry); - return irq; + status = arch_setup_msi_irq(irq, dev); + if (status < 0) { + destroy_msi_irq(irq); + return status; } - entry->link.head = irq; - entry->link.tail = irq; - dev->first_msi_irq = irq; - set_irq_msi(irq, entry); + attach_msi_entry(entry, irq); /* Set MSI enabled bits */ enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); @@ -474,6 +539,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, int nvec) { struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; + int status; int irq, pos, i, j, nr_entries, temp = 0; unsigned long phys_addr; u32 table_offset; @@ -496,11 +562,13 @@ static int msix_capability_init(struct pci_dev *dev, /* MSI-X Table Initialization */ for (i = 0; i < nvec; i++) { - entry = alloc_msi_entry(); - if (!entry) + irq = create_msi_irq(); + if (irq < 0) break; + entry = get_irq_data(irq); j = entries[i].entry; + entries[i].vector = irq; entry->msi_attrib.type = PCI_CAP_ID_MSIX; entry->msi_attrib.is_64 = 1; entry->msi_attrib.entry_nr = j; @@ -509,14 +577,6 @@ static int msix_capability_init(struct pci_dev *dev, entry->msi_attrib.pos = pos; entry->dev = dev; entry->mask_base = base; - - /* Configure MSI-X capability structure */ - irq = arch_setup_msi_irq(dev, entry); - if (irq < 0) { - kmem_cache_free(msi_cachep, entry); - break; - } - entries[i].vector = irq; if (!head) { entry->link.head = irq; entry->link.tail = irq; @@ -529,8 +589,14 @@ static int msix_capability_init(struct pci_dev *dev, } temp = irq; tail = entry; + /* Configure MSI-X capability structure */ + status = arch_setup_msi_irq(irq, dev); + if (status < 0) { + destroy_msi_irq(irq); + break; + } - set_irq_msi(irq, entry); + attach_msi_entry(entry, irq); } if (i != nvec) { int avail = i - 1; @@ -547,7 +613,6 @@ static int msix_capability_init(struct pci_dev *dev, avail = -EBUSY; return avail; } - dev->first_msi_irq = entries[0].vector; /* Set MSI-X enabled bits */ enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); @@ -595,11 +660,13 @@ int pci_msi_supported(struct pci_dev * dev) **/ int pci_enable_msi(struct pci_dev* dev) { - int pos, status; + int pos, temp, status; if (pci_msi_supported(dev) < 0) return -EINVAL; + temp = dev->irq; + status = msi_init(); if (status < 0) return status; @@ -608,14 +675,15 @@ int pci_enable_msi(struct pci_dev* dev) if (!pos) return -EINVAL; - WARN_ON(!!dev->msi_enabled); + WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSI)); /* Check whether driver already requested for MSI-X irqs */ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - if (pos > 0 && dev->msix_enabled) { + if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { printk(KERN_INFO "PCI: %s: Can't enable MSI. " - "Device already has MSI-X enabled\n", + "Device already has MSI-X irq assigned\n", pci_name(dev)); + dev->irq = temp; return -EINVAL; } status = msi_capability_init(dev); @@ -627,15 +695,13 @@ void pci_disable_msi(struct pci_dev* dev) struct msi_desc *entry; int pos, default_irq; u16 control; + unsigned long flags; if (!pci_msi_enable) return; if (!dev) return; - if (!dev->msi_enabled) - return; - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); if (!pos) return; @@ -644,26 +710,28 @@ void pci_disable_msi(struct pci_dev* dev) if (!(control & PCI_MSI_FLAGS_ENABLE)) return; - disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); - entry = get_irq_msi(dev->first_msi_irq); + spin_lock_irqsave(&msi_lock, flags); + entry = msi_desc[dev->irq]; if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { + spin_unlock_irqrestore(&msi_lock, flags); return; } - if (irq_has_action(dev->first_msi_irq)) { + if (irq_has_action(dev->irq)) { + spin_unlock_irqrestore(&msi_lock, flags); printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without " "free_irq() on MSI irq %d\n", - pci_name(dev), dev->first_msi_irq); - BUG_ON(irq_has_action(dev->first_msi_irq)); + pci_name(dev), dev->irq); + BUG_ON(irq_has_action(dev->irq)); } else { default_irq = entry->msi_attrib.default_irq; - msi_free_irq(dev, dev->first_msi_irq); + spin_unlock_irqrestore(&msi_lock, flags); + msi_free_irq(dev, dev->irq); /* Restore dev->irq to its default pin-assertion irq */ dev->irq = default_irq; } - dev->first_msi_irq = 0; } static int msi_free_irq(struct pci_dev* dev, int irq) @@ -671,20 +739,27 @@ static int msi_free_irq(struct pci_dev* dev, int irq) struct msi_desc *entry; int head, entry_nr, type; void __iomem *base; + unsigned long flags; - entry = get_irq_msi(irq); + arch_teardown_msi_irq(irq); + + spin_lock_irqsave(&msi_lock, flags); + entry = msi_desc[irq]; if (!entry || entry->dev != dev) { + spin_unlock_irqrestore(&msi_lock, flags); return -EINVAL; } type = entry->msi_attrib.type; entry_nr = entry->msi_attrib.entry_nr; head = entry->link.head; base = entry->mask_base; - get_irq_msi(entry->link.head)->link.tail = entry->link.tail; - get_irq_msi(entry->link.tail)->link.head = entry->link.head; + msi_desc[entry->link.head]->link.tail = entry->link.tail; + msi_desc[entry->link.tail]->link.head = entry->link.head; + entry->dev = NULL; + msi_desc[irq] = NULL; + spin_unlock_irqrestore(&msi_lock, flags); - arch_teardown_msi_irq(irq); - kmem_cache_free(msi_cachep, entry); + destroy_msi_irq(irq); if (type == PCI_CAP_ID_MSIX) { writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE + @@ -715,7 +790,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq) int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) { int status, pos, nr_entries; - int i, j; + int i, j, temp; u16 control; if (!entries || pci_msi_supported(dev) < 0) @@ -743,14 +818,16 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) return -EINVAL; /* duplicate entry */ } } - WARN_ON(!!dev->msix_enabled); + temp = dev->irq; + WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)); /* Check whether driver already requested for MSI irq */ if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 && - dev->msi_enabled) { + !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) { printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " "Device already has an MSI irq assigned\n", pci_name(dev)); + dev->irq = temp; return -EINVAL; } status = msix_capability_init(dev, entries, nvec); @@ -759,8 +836,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) void pci_disable_msix(struct pci_dev* dev) { - int irq, head, tail = 0, warning = 0; - int pos; + int pos, temp; u16 control; if (!pci_msi_enable) @@ -768,9 +844,6 @@ void pci_disable_msix(struct pci_dev* dev) if (!dev) return; - if (!dev->msix_enabled) - return; - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); if (!pos) return; @@ -781,23 +854,31 @@ void pci_disable_msix(struct pci_dev* dev) disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); - irq = head = dev->first_msi_irq; - while (head != tail) { - tail = get_irq_msi(irq)->link.tail; - if (irq_has_action(irq)) - warning = 1; - else if (irq != head) /* Release MSI-X irq */ - msi_free_irq(dev, irq); - irq = tail; - } - msi_free_irq(dev, irq); - if (warning) { - printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " - "free_irq() on all MSI-X irqs\n", - pci_name(dev)); - BUG_ON(warning > 0); + temp = dev->irq; + if (!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { + int irq, head, tail = 0, warning = 0; + unsigned long flags; + + irq = head = dev->irq; + dev->irq = temp; /* Restore pin IRQ */ + while (head != tail) { + spin_lock_irqsave(&msi_lock, flags); + tail = msi_desc[irq]->link.tail; + spin_unlock_irqrestore(&msi_lock, flags); + if (irq_has_action(irq)) + warning = 1; + else if (irq != head) /* Release MSI-X irq */ + msi_free_irq(dev, irq); + irq = tail; + } + msi_free_irq(dev, irq); + if (warning) { + printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " + "free_irq() on all MSI-X irqs\n", + pci_name(dev)); + BUG_ON(warning > 0); + } } - dev->first_msi_irq = 0; } /** @@ -811,26 +892,35 @@ void pci_disable_msix(struct pci_dev* dev) **/ void msi_remove_pci_irq_vectors(struct pci_dev* dev) { + int pos, temp; + unsigned long flags; + if (!pci_msi_enable || !dev) return; - if (dev->msi_enabled) { - if (irq_has_action(dev->first_msi_irq)) { + temp = dev->irq; /* Save IOAPIC IRQ */ + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) { + if (irq_has_action(dev->irq)) { printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " "called without free_irq() on MSI irq %d\n", - pci_name(dev), dev->first_msi_irq); - BUG_ON(irq_has_action(dev->first_msi_irq)); + pci_name(dev), dev->irq); + BUG_ON(irq_has_action(dev->irq)); } else /* Release MSI irq assigned to this device */ - msi_free_irq(dev, dev->first_msi_irq); + msi_free_irq(dev, dev->irq); + dev->irq = temp; /* Restore IOAPIC IRQ */ } - if (dev->msix_enabled) { + pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { int irq, head, tail = 0, warning = 0; void __iomem *base = NULL; - irq = head = dev->first_msi_irq; + irq = head = dev->irq; while (head != tail) { - tail = get_irq_msi(irq)->link.tail; - base = get_irq_msi(irq)->mask_base; + spin_lock_irqsave(&msi_lock, flags); + tail = msi_desc[irq]->link.tail; + base = msi_desc[irq]->mask_base; + spin_unlock_irqrestore(&msi_lock, flags); if (irq_has_action(irq)) warning = 1; else if (irq != head) /* Release MSI-X irq */ @@ -845,6 +935,7 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) pci_name(dev)); BUG_ON(warning > 0); } + dev->irq = temp; /* Restore IOAPIC IRQ */ } } diff --git a/trunk/drivers/pci/pci-driver.c b/trunk/drivers/pci/pci-driver.c index 4438ae1ede4f..92d5e8db0de7 100644 --- a/trunk/drivers/pci/pci-driver.c +++ b/trunk/drivers/pci/pci-driver.c @@ -324,7 +324,8 @@ static int pci_default_resume(struct pci_dev *pci_dev) /* restore the PCI config space */ pci_restore_state(pci_dev); /* if the device was enabled before suspend, reenable */ - retval = __pci_reenable_device(pci_dev); + if (atomic_read(&pci_dev->enable_cnt)) + retval = __pci_enable_device(pci_dev); /* if the device was busmaster before the suspend, make it busmaster again */ if (pci_dev->is_busmaster) pci_set_master(pci_dev); @@ -421,8 +422,7 @@ static struct kobj_type pci_driver_kobj_type = { * If no error occurred, the driver remains registered even if * no device was claimed during registration. */ -int __pci_register_driver(struct pci_driver *drv, struct module *owner, - const char *mod_name) +int __pci_register_driver(struct pci_driver *drv, struct module *owner) { int error; @@ -430,7 +430,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, drv->driver.name = drv->name; drv->driver.bus = &pci_bus_type; drv->driver.owner = owner; - drv->driver.mod_name = mod_name; drv->driver.kobj.ktype = &pci_driver_kobj_type; if (pci_multithread_probe) diff --git a/trunk/drivers/pci/pci.c b/trunk/drivers/pci/pci.c index 84c757ba0664..206c834d263a 100644 --- a/trunk/drivers/pci/pci.c +++ b/trunk/drivers/pci/pci.c @@ -392,14 +392,6 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) if (state > PCI_D3hot) state = PCI_D3hot; - /* - * If the device or the parent bridge can't support PCI PM, ignore - * the request if we're doing anything besides putting it into D0 - * (which would only happen on boot). - */ - if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev)) - return 0; - /* Validate current state: * Can enter D0 from any state, but if we can only go deeper * to sleep if we're already in a low power state @@ -411,6 +403,13 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) } else if (dev->current_state == state) return 0; /* we're already there */ + /* + * If the device or the parent bridge can't support PCI PM, ignore + * the request if we're doing anything besides putting it into D0 + * (which would only happen on boot). + */ + if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev)) + return 0; /* find PCI PM capability in list */ pm = pci_find_capability(dev, PCI_CAP_ID_PM); @@ -634,6 +633,8 @@ pci_save_state(struct pci_dev *dev) pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); if ((i = pci_save_msi_state(dev)) != 0) return i; + if ((i = pci_save_msix_state(dev)) != 0) + return i; if ((i = pci_save_pcie_state(dev)) != 0) return i; if ((i = pci_save_pcix_state(dev)) != 0) @@ -671,11 +672,22 @@ pci_restore_state(struct pci_dev *dev) } pci_restore_pcix_state(dev); pci_restore_msi_state(dev); - + pci_restore_msix_state(dev); return 0; } -static int do_pci_enable_device(struct pci_dev *dev, int bars) +/** + * pci_enable_device_bars - Initialize some of a device for use + * @dev: PCI device to be initialized + * @bars: bitmask of BAR's that must be configured + * + * Initialize device before it's used by a driver. Ask low-level code + * to enable selected I/O and memory resources. Wake up the device if it + * was suspended. Beware, this function can fail. + */ + +int +pci_enable_device_bars(struct pci_dev *dev, int bars) { int err; @@ -685,47 +697,30 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) err = pcibios_enable_device(dev, bars); if (err < 0) return err; - pci_fixup_device(pci_fixup_enable, dev); - return 0; } /** - * __pci_reenable_device - Resume abandoned device - * @dev: PCI device to be resumed - * - * Note this function is a backend of pci_default_resume and is not supposed - * to be called by normal code, write proper resume handler and use it instead. - */ -int -__pci_reenable_device(struct pci_dev *dev) -{ - if (atomic_read(&dev->enable_cnt)) - return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1); - return 0; -} - -/** - * pci_enable_device_bars - Initialize some of a device for use + * __pci_enable_device - Initialize device before it's used by a driver. * @dev: PCI device to be initialized - * @bars: bitmask of BAR's that must be configured * * Initialize device before it's used by a driver. Ask low-level code - * to enable selected I/O and memory resources. Wake up the device if it - * was suspended. Beware, this function can fail. + * to enable I/O and memory. Wake up the device if it was suspended. + * Beware, this function can fail. + * + * Note this function is a backend and is not supposed to be called by + * normal code, use pci_enable_device() instead. */ int -pci_enable_device_bars(struct pci_dev *dev, int bars) +__pci_enable_device(struct pci_dev *dev) { int err; - if (atomic_add_return(1, &dev->enable_cnt) > 1) - return 0; /* already enabled */ - - err = do_pci_enable_device(dev, bars); - if (err < 0) - atomic_dec(&dev->enable_cnt); - return err; + err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + if (err) + return err; + pci_fixup_device(pci_fixup_enable, dev); + return 0; } /** @@ -741,7 +736,13 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) */ int pci_enable_device(struct pci_dev *dev) { - return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); + int result; + if (atomic_add_return(1, &dev->enable_cnt) > 1) + return 0; /* already enabled */ + result = __pci_enable_device(dev); + if (result < 0) + atomic_dec(&dev->enable_cnt); + return result; } /** @@ -920,47 +921,6 @@ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) return -EBUSY; } -/** - * pci_release_selected_regions - Release selected PCI I/O and memory resources - * @pdev: PCI device whose resources were previously reserved - * @bars: Bitmask of BARs to be released - * - * Release selected PCI I/O and memory resources previously reserved. - * Call this function only after all use of the PCI regions has ceased. - */ -void pci_release_selected_regions(struct pci_dev *pdev, int bars) -{ - int i; - - for (i = 0; i < 6; i++) - if (bars & (1 << i)) - pci_release_region(pdev, i); -} - -/** - * pci_request_selected_regions - Reserve selected PCI I/O and memory resources - * @pdev: PCI device whose resources are to be reserved - * @bars: Bitmask of BARs to be requested - * @res_name: Name to be associated with resource - */ -int pci_request_selected_regions(struct pci_dev *pdev, int bars, - const char *res_name) -{ - int i; - - for (i = 0; i < 6; i++) - if (bars & (1 << i)) - if(pci_request_region(pdev, i, res_name)) - goto err_out; - return 0; - -err_out: - while(--i >= 0) - if (bars & (1 << i)) - pci_release_region(pdev, i); - - return -EBUSY; -} /** * pci_release_regions - Release reserved PCI I/O and memory resources @@ -973,7 +933,10 @@ int pci_request_selected_regions(struct pci_dev *pdev, int bars, void pci_release_regions(struct pci_dev *pdev) { - pci_release_selected_regions(pdev, (1 << 6) - 1); + int i; + + for (i = 0; i < 6; i++) + pci_release_region(pdev, i); } /** @@ -991,7 +954,18 @@ void pci_release_regions(struct pci_dev *pdev) */ int pci_request_regions(struct pci_dev *pdev, const char *res_name) { - return pci_request_selected_regions(pdev, ((1 << 6) - 1), res_name); + int i; + + for (i = 0; i < 6; i++) + if(pci_request_region(pdev, i, res_name)) + goto err_out; + return 0; + +err_out: + while(--i >= 0) + pci_release_region(pdev, i); + + return -EBUSY; } /** @@ -1174,23 +1148,7 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) return 0; } #endif - -/** - * pci_select_bars - Make BAR mask from the type of resource - * @pdev: the PCI device for which BAR mask is made - * @flags: resource type mask to be selected - * - * This helper routine makes bar mask from the type of resource. - */ -int pci_select_bars(struct pci_dev *dev, unsigned long flags) -{ - int i, bars = 0; - for (i = 0; i < PCI_NUM_RESOURCES; i++) - if (pci_resource_flags(dev, i) & flags) - bars |= (1 << i); - return bars; -} - + static int __devinit pci_init(void) { struct pci_dev *dev = NULL; @@ -1223,6 +1181,12 @@ early_param("pci", pci_setup); device_initcall(pci_init); +#if defined(CONFIG_ISA) || defined(CONFIG_EISA) +/* FIXME: Some boxes have multiple ISA bridges! */ +struct pci_dev *isa_bridge; +EXPORT_SYMBOL(isa_bridge); +#endif + EXPORT_SYMBOL_GPL(pci_restore_bars); EXPORT_SYMBOL(pci_enable_device_bars); EXPORT_SYMBOL(pci_enable_device); @@ -1233,8 +1197,6 @@ EXPORT_SYMBOL(pci_release_regions); EXPORT_SYMBOL(pci_request_regions); EXPORT_SYMBOL(pci_release_region); EXPORT_SYMBOL(pci_request_region); -EXPORT_SYMBOL(pci_release_selected_regions); -EXPORT_SYMBOL(pci_request_selected_regions); EXPORT_SYMBOL(pci_set_master); EXPORT_SYMBOL(pci_set_mwi); EXPORT_SYMBOL(pci_clear_mwi); @@ -1243,10 +1205,13 @@ EXPORT_SYMBOL(pci_set_dma_mask); EXPORT_SYMBOL(pci_set_consistent_dma_mask); EXPORT_SYMBOL(pci_assign_resource); EXPORT_SYMBOL(pci_find_parent_resource); -EXPORT_SYMBOL(pci_select_bars); EXPORT_SYMBOL(pci_set_power_state); EXPORT_SYMBOL(pci_save_state); EXPORT_SYMBOL(pci_restore_state); EXPORT_SYMBOL(pci_enable_wake); +/* Quirk info */ + +EXPORT_SYMBOL(isa_dma_bridge_buggy); +EXPORT_SYMBOL(pci_pci_problems); diff --git a/trunk/drivers/pci/pci.h b/trunk/drivers/pci/pci.h index a4f2d580625e..398852f526a6 100644 --- a/trunk/drivers/pci/pci.h +++ b/trunk/drivers/pci/pci.h @@ -1,6 +1,6 @@ /* Functions internal to the PCI core code */ -extern int __must_check __pci_reenable_device(struct pci_dev *); +extern int __must_check __pci_enable_device(struct pci_dev *); extern int pci_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); @@ -43,8 +43,12 @@ extern void pci_remove_legacy_files(struct pci_bus *bus); /* Lock for read/write access to pci device and bus lists */ extern struct rw_semaphore pci_bus_sem; +#ifdef CONFIG_PCI_MSI +extern int pci_msi_quirk; +#else +#define pci_msi_quirk 0 +#endif extern unsigned int pci_pm_d3_delay; - #ifdef CONFIG_PCI_MSI void disable_msi_mode(struct pci_dev *dev, int pos, int type); void pci_no_msi(void); @@ -52,15 +56,17 @@ void pci_no_msi(void); static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } static inline void pci_no_msi(void) { } #endif - #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM) int pci_save_msi_state(struct pci_dev *dev); +int pci_save_msix_state(struct pci_dev *dev); void pci_restore_msi_state(struct pci_dev *dev); +void pci_restore_msix_state(struct pci_dev *dev); #else static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; } +static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; } static inline void pci_restore_msi_state(struct pci_dev *dev) {} +static inline void pci_restore_msix_state(struct pci_dev *dev) {} #endif - static inline int pci_no_d1d2(struct pci_dev *dev) { unsigned int parent_dstates = 0; diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index 2fe1d690eb13..0e0401dd02cb 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -144,32 +144,6 @@ static u32 pci_size(u32 base, u32 maxbase, u32 mask) return size; } -static u64 pci_size64(u64 base, u64 maxbase, u64 mask) -{ - u64 size = mask & maxbase; /* Find the significant bits */ - if (!size) - return 0; - - /* Get the lowest of them to find the decode size, and - from that the extent. */ - size = (size & ~(size-1)) - 1; - - /* base == maxbase can be valid only if the BAR has - already been programmed with all 1s. */ - if (base == maxbase && ((base | size) & mask) != mask) - return 0; - - return size; -} - -static inline int is_64bit_memory(u32 mask) -{ - if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == - (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64)) - return 1; - return 0; -} - static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) { unsigned int pos, reg, next; @@ -177,10 +151,6 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) struct resource *res; for(pos=0; posresource[pos]; res->name = pci_name(dev); @@ -193,16 +163,9 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) continue; if (l == 0xffffffff) l = 0; - raw_sz = sz; - if ((l & PCI_BASE_ADDRESS_SPACE) == - PCI_BASE_ADDRESS_SPACE_MEMORY) { + if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) { sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK); - /* - * For 64bit prefetchable memory sz could be 0, if the - * real size is bigger than 4G, so we need to check - * szhi for that. - */ - if (!is_64bit_memory(l) && !sz) + if (!sz) continue; res->start = l & PCI_BASE_ADDRESS_MEM_MASK; res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; @@ -215,36 +178,30 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) } res->end = res->start + (unsigned long) sz; res->flags |= pci_calc_resource_flags(l); - if (is_64bit_memory(l)) { + if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) + == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { u32 szhi, lhi; - pci_read_config_dword(dev, reg+4, &lhi); pci_write_config_dword(dev, reg+4, ~0); pci_read_config_dword(dev, reg+4, &szhi); pci_write_config_dword(dev, reg+4, lhi); - sz64 = ((u64)szhi << 32) | raw_sz; - l64 = ((u64)lhi << 32) | l; - sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK); + szhi = pci_size(lhi, szhi, 0xffffffff); next++; #if BITS_PER_LONG == 64 - if (!sz64) { - res->start = 0; - res->end = 0; - res->flags = 0; - continue; + res->start |= ((unsigned long) lhi) << 32; + res->end = res->start + sz; + if (szhi) { + /* This BAR needs > 4GB? Wow. */ + res->end |= (unsigned long)szhi<<32; } - res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK; - res->end = res->start + sz64; #else - if (sz64 > 0x100000000ULL) { - printk(KERN_ERR "PCI: Unable to handle 64-bit " - "BAR for device %s\n", pci_name(dev)); + if (szhi) { + printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev)); res->start = 0; res->flags = 0; } else if (lhi) { /* 64-bit wide address, treat as disabled */ - pci_write_config_dword(dev, reg, - l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); + pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); pci_write_config_dword(dev, reg+4, 0); res->start = 0; res->end = sz; @@ -945,6 +902,7 @@ pci_scan_single_device(struct pci_bus *bus, int devfn) return NULL; pci_device_add(dev, bus); + pci_scan_msi_device(dev); return dev; } diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index 11217bda4b9e..c913ea4e545c 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -61,8 +61,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_p This appears to be BIOS not version dependent. So presumably there is a chipset level fix */ -int isa_dma_bridge_buggy; -EXPORT_SYMBOL(isa_dma_bridge_buggy); +int isa_dma_bridge_buggy; /* Exported */ static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev) { @@ -84,7 +83,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_d DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs ); int pci_pci_problems; -EXPORT_SYMBOL(pci_pci_problems); /* * Chipsets where PCI->PCI transfers vanish or hang @@ -96,8 +94,6 @@ static void __devinit quirk_nopcipci(struct pci_dev *dev) pci_pci_problems |= PCIPCI_FAIL; } } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci ); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci ); static void __devinit quirk_nopciamd(struct pci_dev *dev) { @@ -109,6 +105,9 @@ static void __devinit quirk_nopciamd(struct pci_dev *dev) pci_pci_problems |= PCIAGP_FAIL; } } + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci ); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci ); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopciamd ); /* @@ -977,51 +976,52 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x1626: /* L3C notebook */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) + if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) switch(dev->subsystem_device) { case 0x80b1: /* P4GE-V */ case 0x80b2: /* P4PE */ case 0x8093: /* P4B533-V */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82850_HB) + if (dev->device == PCI_DEVICE_ID_INTEL_82850_HB) switch(dev->subsystem_device) { case 0x8030: /* P4T533 */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_7205_0) + if (dev->device == PCI_DEVICE_ID_INTEL_7205_0) switch (dev->subsystem_device) { case 0x8070: /* P4G8X Deluxe */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH) + if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH) switch (dev->subsystem_device) { case 0x80c9: /* PU-DLS */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) + if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) switch (dev->subsystem_device) { case 0x1751: /* M2N notebook */ case 0x1821: /* M5N notebook */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) + if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) switch (dev->subsystem_device) { case 0x184b: /* W1N notebook */ case 0x186a: /* M6Ne notebook */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB) + if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB) switch (dev->subsystem_device) { case 0x80f2: /* P4P800-X */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) + if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) { switch (dev->subsystem_device) { case 0x1882: /* M6V notebook */ case 0x1977: /* A6VA notebook */ asus_hides_smbus = 1; } + } } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) { if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) switch(dev->subsystem_device) { @@ -1029,24 +1029,25 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x0890: /* HP Compaq nc6000 */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB) + if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB) switch (dev->subsystem_device) { case 0x12bc: /* HP D330L */ case 0x12bd: /* HP D530 */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) + if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) { switch (dev->subsystem_device) { case 0x099c: /* HP Compaq nx6110 */ asus_hides_smbus = 1; } + } } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) { if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) switch(dev->subsystem_device) { case 0x0001: /* Toshiba Satellite A40 */ asus_hides_smbus = 1; } - else if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) + if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) switch(dev->subsystem_device) { case 0x0001: /* Toshiba Tecra M2 */ asus_hides_smbus = 1; @@ -1135,14 +1136,6 @@ static void quirk_sis_96x_smbus(struct pci_dev *dev) pci_write_config_byte(dev, 0x77, val & ~0x10); } } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); /* * ... This is further complicated by the fact that some SiS96x south @@ -1152,6 +1145,8 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_ * * We can also enable the sis96x bit in the discovery register.. */ +static int __devinitdata sis_96x_compatible = 0; + #define SIS_DETECT_REGISTER 0x40 static void quirk_sis_503(struct pci_dev *dev) @@ -1167,6 +1162,9 @@ static void quirk_sis_503(struct pci_dev *dev) return; } + /* Make people aware that we changed the config.. */ + printk(KERN_WARNING "Uncovering SIS%x that hid as a SIS503 (compatible=%d)\n", devid, sis_96x_compatible); + /* * Ok, it now shows up as a 96x.. run the 96x quirk by * hand in case it has already been processed. @@ -1175,10 +1173,20 @@ static void quirk_sis_503(struct pci_dev *dev) dev->device = devid; quirk_sis_96x_smbus(dev); } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); +static void __init quirk_sis_96x_compatible(struct pci_dev *dev) +{ + sis_96x_compatible = 1; +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_645, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_646, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_648, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_651, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_735, quirk_sis_96x_compatible ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 ); /* * On ASUS A8V and A8V Deluxe boards, the onboard AC97 audio controller * and MC97 modem controller are disabled when a second PCI soundcard is @@ -1209,8 +1217,21 @@ static void asus_hides_ac97_lpc(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); + + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); + DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc ); + +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); + #if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE) /* @@ -1255,6 +1276,7 @@ static void quirk_jmicron_dualfn(struct pci_dev *pdev) break; } } + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn); @@ -1398,7 +1420,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_co int pcie_mch_quirk; -EXPORT_SYMBOL(pcie_mch_quirk); static void __devinit quirk_pcie_mch(struct pci_dev *pdev) { @@ -1460,24 +1481,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); -/* - * Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size - * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes. - * Re-allocate the region if needed... - */ -static void __init quirk_tc86c001_ide(struct pci_dev *dev) -{ - struct resource *r = &dev->resource[0]; - - if (r->start & 0x8) { - r->start = 0; - r->end = 0xf; - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2, - PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE, - quirk_tc86c001_ide); - static void __devinit quirk_netmos(struct pci_dev *dev) { unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; @@ -1643,7 +1646,6 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) } pci_do_fixups(dev, start, end); } -EXPORT_SYMBOL(pci_fixup_device); /* Enable 1k I/O space granularity on the Intel P64H2 */ static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) @@ -1671,31 +1673,6 @@ static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); -/* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2 - * The IOBL_ADR gets re-written to 4k boundaries in pci_setup_bridge() - * in drivers/pci/setup-bus.c - */ -static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev) -{ - u16 en1k, iobl_adr, iobl_adr_1k; - struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES; - - pci_read_config_word(dev, 0x40, &en1k); - - if (en1k & 0x200) { - pci_read_config_word(dev, PCI_IO_BASE, &iobl_adr); - - iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00); - - if (iobl_adr != iobl_adr_1k) { - printk(KERN_INFO "PCI: Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1 KB Granularity\n", - iobl_adr,iobl_adr_1k); - pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k); - } - } -} -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io_fix_iobl); - /* Under some circumstances, AER is not linked with extended capabilities. * Force it to be linked by setting the corresponding control bit in the * config space. @@ -1718,6 +1695,9 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_pcie_aer_ext_cap); #ifdef CONFIG_PCI_MSI +/* To disable MSI globally */ +int pci_msi_quirk; + /* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely * on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually * some other busses controlled by the chipset even if Linux is not aware of it. @@ -1726,8 +1706,8 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, */ static void __init quirk_svw_msi(struct pci_dev *dev) { - pci_no_msi(); - printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n"); + pci_msi_quirk = 1; + printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n"); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi); @@ -1808,3 +1788,8 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_msi_ht_cap); #endif /* CONFIG_PCI_MSI */ + +EXPORT_SYMBOL(pcie_mch_quirk); +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pci_fixup_device); +#endif diff --git a/trunk/drivers/pci/search.c b/trunk/drivers/pci/search.c index ff98eaddaa73..b2653c4afe9e 100644 --- a/trunk/drivers/pci/search.c +++ b/trunk/drivers/pci/search.c @@ -357,6 +357,43 @@ pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev return dev; } +/** + * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id + * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids + * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids + * @from: Previous PCI device found in search, or %NULL for new search. + * + * Iterates through the list of known PCI devices in the reverse order of + * pci_find_device(). + * If a PCI device is found with a matching @vendor and @device, a pointer to + * its device structure is returned. Otherwise, %NULL is returned. + * A new search is initiated by passing %NULL as the @from argument. + * Otherwise if @from is not %NULL, searches continue from previous device + * on the global list. + */ +struct pci_dev * +pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from) +{ + struct list_head *n; + struct pci_dev *dev; + + WARN_ON(in_interrupt()); + down_read(&pci_bus_sem); + n = from ? from->global_list.prev : pci_devices.prev; + + while (n && (n != &pci_devices)) { + dev = pci_dev_g(n); + if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && + (device == PCI_ANY_ID || dev->device == device)) + goto exit; + n = n->prev; + } + dev = NULL; +exit: + up_read(&pci_bus_sem); + return dev; +} + /** * pci_get_class - begin or continue searching for a PCI device by class * @class: search for a PCI device with this class designation @@ -432,6 +469,7 @@ EXPORT_SYMBOL(pci_dev_present); EXPORT_SYMBOL(pci_find_present); EXPORT_SYMBOL(pci_find_device); +EXPORT_SYMBOL(pci_find_device_reverse); EXPORT_SYMBOL(pci_find_slot); /* For boot time work */ EXPORT_SYMBOL(pci_find_bus); diff --git a/trunk/drivers/pcmcia/cs.c b/trunk/drivers/pcmcia/cs.c index ac004248324a..606a46740338 100644 --- a/trunk/drivers/pcmcia/cs.c +++ b/trunk/drivers/pcmcia/cs.c @@ -110,7 +110,7 @@ int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state) down_read(&pcmcia_socket_list_rwsem); list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { - if (socket->dev.parent != dev) + if (socket->dev.dev != dev) continue; mutex_lock(&socket->skt_mutex); socket_suspend(socket); @@ -128,7 +128,7 @@ int pcmcia_socket_dev_resume(struct device *dev) down_read(&pcmcia_socket_list_rwsem); list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { - if (socket->dev.parent != dev) + if (socket->dev.dev != dev) continue; mutex_lock(&socket->skt_mutex); socket_resume(socket); @@ -143,12 +143,12 @@ EXPORT_SYMBOL(pcmcia_socket_dev_resume); struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt) { - struct device *dev = get_device(&skt->dev); - if (!dev) + struct class_device *cl_dev = class_device_get(&skt->dev); + if (!cl_dev) return NULL; - skt = dev_get_drvdata(dev); + skt = class_get_devdata(cl_dev); if (!try_module_get(skt->owner)) { - put_device(&skt->dev); + class_device_put(&skt->dev); return NULL; } return (skt); @@ -159,14 +159,14 @@ EXPORT_SYMBOL(pcmcia_get_socket); void pcmcia_put_socket(struct pcmcia_socket *skt) { module_put(skt->owner); - put_device(&skt->dev); + class_device_put(&skt->dev); } EXPORT_SYMBOL(pcmcia_put_socket); -static void pcmcia_release_socket(struct device *dev) +static void pcmcia_release_socket(struct class_device *class_dev) { - struct pcmcia_socket *socket = dev_get_drvdata(dev); + struct pcmcia_socket *socket = class_get_devdata(class_dev); complete(&socket->socket_released); } @@ -181,7 +181,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) struct task_struct *tsk; int ret; - if (!socket || !socket->ops || !socket->dev.parent || !socket->resource_ops) + if (!socket || !socket->ops || !socket->dev.dev || !socket->resource_ops) return -EINVAL; cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops); @@ -226,9 +226,9 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) #endif /* set proper values in socket->dev */ - dev_set_drvdata(&socket->dev, socket); + socket->dev.class_data = socket; socket->dev.class = &pcmcia_socket_class; - snprintf(socket->dev.bus_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock); + snprintf(socket->dev.class_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock); /* base address = 0, map = 0 */ socket->cis_mem.flags = 0; @@ -640,7 +640,7 @@ static int pccardd(void *__skt) skt->ops->set_socket(skt, &skt->socket); /* register with the device core */ - ret = device_register(&skt->dev); + ret = class_device_register(&skt->dev); if (ret) { printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n", skt); @@ -689,7 +689,7 @@ static int pccardd(void *__skt) remove_wait_queue(&skt->thread_wait, &wait); /* remove from the device core */ - device_unregister(&skt->dev); + class_device_unregister(&skt->dev); return 0; } @@ -904,7 +904,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) EXPORT_SYMBOL(pcmcia_insert_card); -static int pcmcia_socket_uevent(struct device *dev, char **envp, +static int pcmcia_socket_uevent(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); @@ -930,8 +930,8 @@ static void pcmcia_release_socket_class(struct class *data) struct class pcmcia_socket_class = { .name = "pcmcia_socket", - .dev_uevent = pcmcia_socket_uevent, - .dev_release = pcmcia_release_socket, + .uevent = pcmcia_socket_uevent, + .release = pcmcia_release_socket, .class_release = pcmcia_release_socket_class, }; EXPORT_SYMBOL(pcmcia_socket_class); diff --git a/trunk/drivers/pcmcia/cs_internal.h b/trunk/drivers/pcmcia/cs_internal.h index 9fa207e3c7b3..f573ea04db6f 100644 --- a/trunk/drivers/pcmcia/cs_internal.h +++ b/trunk/drivers/pcmcia/cs_internal.h @@ -142,7 +142,7 @@ struct pcmcia_callback{ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); -#define cs_socket_name(skt) ((skt)->dev.bus_id) +#define cs_socket_name(skt) ((skt)->dev.class_id) #ifdef DEBUG extern int cs_debug_level(int); @@ -158,6 +158,6 @@ extern int cs_debug_level(int); #endif #define cs_err(skt, fmt, arg...) \ - printk(KERN_ERR "cs: %s: " fmt, (skt)->dev.bus_id , ## arg) + printk(KERN_ERR "cs: %s: " fmt, (skt)->dev.class_id , ## arg) #endif /* _LINUX_CS_INTERNAL_H */ diff --git a/trunk/drivers/pcmcia/ds.c b/trunk/drivers/pcmcia/ds.c index 18e111e12339..7355eb455a88 100644 --- a/trunk/drivers/pcmcia/ds.c +++ b/trunk/drivers/pcmcia/ds.c @@ -572,7 +572,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f p_dev->func = function; p_dev->dev.bus = &pcmcia_bus_type; - p_dev->dev.parent = s->dev.parent; + p_dev->dev.parent = s->dev.dev; p_dev->dev.release = pcmcia_release_dev; bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); @@ -1328,10 +1328,10 @@ static struct pcmcia_callback pcmcia_bus_callback = { .resume = pcmcia_bus_resume, }; -static int __devinit pcmcia_bus_add_socket(struct device *dev, +static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev, struct class_interface *class_intf) { - struct pcmcia_socket *socket = dev_get_drvdata(dev); + struct pcmcia_socket *socket = class_get_devdata(class_dev); int ret; socket = pcmcia_get_socket(socket); @@ -1364,10 +1364,10 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev, return 0; } -static void pcmcia_bus_remove_socket(struct device *dev, +static void pcmcia_bus_remove_socket(struct class_device *class_dev, struct class_interface *class_intf) { - struct pcmcia_socket *socket = dev_get_drvdata(dev); + struct pcmcia_socket *socket = class_get_devdata(class_dev); if (!socket) return; @@ -1389,8 +1389,8 @@ static void pcmcia_bus_remove_socket(struct device *dev, /* the pcmcia_bus_interface is used to handle pcmcia socket devices */ static struct class_interface pcmcia_bus_interface = { .class = &pcmcia_socket_class, - .add_dev = &pcmcia_bus_add_socket, - .remove_dev = &pcmcia_bus_remove_socket, + .add = &pcmcia_bus_add_socket, + .remove = &pcmcia_bus_remove_socket, }; diff --git a/trunk/drivers/pcmcia/i82092.c b/trunk/drivers/pcmcia/i82092.c index df21e2d16f87..c2ea07aa7a12 100644 --- a/trunk/drivers/pcmcia/i82092.c +++ b/trunk/drivers/pcmcia/i82092.c @@ -161,7 +161,7 @@ static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_de pci_set_drvdata(dev, &sockets[i].socket); for (i = 0; idev; + sockets[i].socket.dev.dev = &dev->dev; sockets[i].socket.ops = &i82092aa_operations; sockets[i].socket.resource_ops = &pccard_nonstatic_ops; ret = pcmcia_register_socket(&sockets[i].socket); diff --git a/trunk/drivers/pcmcia/i82365.c b/trunk/drivers/pcmcia/i82365.c index 72ff2f615b33..ea74f98a7350 100644 --- a/trunk/drivers/pcmcia/i82365.c +++ b/trunk/drivers/pcmcia/i82365.c @@ -1298,7 +1298,7 @@ static int __init init_i82365(void) /* register sockets with the pcmcia core */ for (i = 0; i < sockets; i++) { - socket[i].socket.dev.parent = &i82365_device->dev; + socket[i].socket.dev.dev = &i82365_device->dev; socket[i].socket.ops = &pcic_operations; socket[i].socket.resource_ops = &pccard_nonstatic_ops; socket[i].socket.owner = THIS_MODULE; diff --git a/trunk/drivers/pcmcia/pcmcia_ioctl.c b/trunk/drivers/pcmcia/pcmcia_ioctl.c index 88494149e910..327372b7a54e 100644 --- a/trunk/drivers/pcmcia/pcmcia_ioctl.c +++ b/trunk/drivers/pcmcia/pcmcia_ioctl.c @@ -59,6 +59,7 @@ typedef struct user_info_t { #ifdef DEBUG extern int ds_pc_debug; +#define cs_socket_name(skt) ((skt)->dev.class_id) #define ds_dbg(lvl, fmt, arg...) do { \ if (ds_pc_debug >= lvl) \ diff --git a/trunk/drivers/pcmcia/pcmcia_resource.c b/trunk/drivers/pcmcia/pcmcia_resource.c index 0ce39de834c4..b9201c2ec38b 100644 --- a/trunk/drivers/pcmcia/pcmcia_resource.c +++ b/trunk/drivers/pcmcia/pcmcia_resource.c @@ -48,6 +48,7 @@ static u8 pcmcia_used_irq[NR_IRQS]; #ifdef DEBUG extern int ds_pc_debug; +#define cs_socket_name(skt) ((skt)->dev.class_id) #define ds_dbg(skt, lvl, fmt, arg...) do { \ if (ds_pc_debug >= lvl) \ diff --git a/trunk/drivers/pcmcia/pd6729.c b/trunk/drivers/pcmcia/pd6729.c index dd0ddf19ee57..360c24896548 100644 --- a/trunk/drivers/pcmcia/pd6729.c +++ b/trunk/drivers/pcmcia/pd6729.c @@ -682,7 +682,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, socket[i].socket.ops = &pd6729_operations; socket[i].socket.resource_ops = &pccard_nonstatic_ops; - socket[i].socket.dev.parent = &dev->dev; + socket[i].socket.dev.dev = &dev->dev; socket[i].socket.driver_data = &socket[i]; } diff --git a/trunk/drivers/pcmcia/rsrc_nonstatic.c b/trunk/drivers/pcmcia/rsrc_nonstatic.c index bfcaad6021cf..c3176b16b7be 100644 --- a/trunk/drivers/pcmcia/rsrc_nonstatic.c +++ b/trunk/drivers/pcmcia/rsrc_nonstatic.c @@ -616,7 +616,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star static struct resource *nonstatic_find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { - struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.bus_id); + struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id); struct socket_data *s_data = s->resource_data; struct pcmcia_align_data data; unsigned long min = base; @@ -650,7 +650,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, static struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align, int low, struct pcmcia_socket *s) { - struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.bus_id); + struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id); struct socket_data *s_data = s->resource_data; struct pcmcia_align_data data; unsigned long min, max; @@ -897,10 +897,9 @@ EXPORT_SYMBOL(pccard_nonstatic_ops); /* sysfs interface to the resource database */ -static ssize_t show_io_db(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_io_db(struct class_device *class_dev, char *buf) { - struct pcmcia_socket *s = dev_get_drvdata(dev); + struct pcmcia_socket *s = class_get_devdata(class_dev); struct socket_data *data; struct resource_map *p; ssize_t ret = 0; @@ -921,11 +920,9 @@ static ssize_t show_io_db(struct device *dev, return (ret); } -static ssize_t store_io_db(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size_t count) { - struct pcmcia_socket *s = dev_get_drvdata(dev); + struct pcmcia_socket *s = class_get_devdata(class_dev); unsigned long start_addr, end_addr; unsigned int add = ADD_MANAGED_RESOURCE; ssize_t ret = 0; @@ -950,12 +947,11 @@ static ssize_t store_io_db(struct device *dev, return ret ? ret : count; } -static DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db); +static CLASS_DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db); -static ssize_t show_mem_db(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_mem_db(struct class_device *class_dev, char *buf) { - struct pcmcia_socket *s = dev_get_drvdata(dev); + struct pcmcia_socket *s = class_get_devdata(class_dev); struct socket_data *data; struct resource_map *p; ssize_t ret = 0; @@ -976,11 +972,9 @@ static ssize_t show_mem_db(struct device *dev, return (ret); } -static ssize_t store_mem_db(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, size_t count) { - struct pcmcia_socket *s = dev_get_drvdata(dev); + struct pcmcia_socket *s = class_get_devdata(class_dev); unsigned long start_addr, end_addr; unsigned int add = ADD_MANAGED_RESOURCE; ssize_t ret = 0; @@ -1005,25 +999,25 @@ static ssize_t store_mem_db(struct device *dev, return ret ? ret : count; } -static DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db); +static CLASS_DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db); -static struct device_attribute *pccard_rsrc_attributes[] = { - &dev_attr_available_resources_io, - &dev_attr_available_resources_mem, +static struct class_device_attribute *pccard_rsrc_attributes[] = { + &class_device_attr_available_resources_io, + &class_device_attr_available_resources_mem, NULL, }; -static int __devinit pccard_sysfs_add_rsrc(struct device *dev, +static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev, struct class_interface *class_intf) { - struct pcmcia_socket *s = dev_get_drvdata(dev); - struct device_attribute **attr; + struct pcmcia_socket *s = class_get_devdata(class_dev); + struct class_device_attribute **attr; int ret = 0; if (s->resource_ops != &pccard_nonstatic_ops) return 0; for (attr = pccard_rsrc_attributes; *attr; attr++) { - ret = device_create_file(dev, *attr); + ret = class_device_create_file(class_dev, *attr); if (ret) break; } @@ -1031,23 +1025,23 @@ static int __devinit pccard_sysfs_add_rsrc(struct device *dev, return ret; } -static void __devexit pccard_sysfs_remove_rsrc(struct device *dev, +static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev, struct class_interface *class_intf) { - struct pcmcia_socket *s = dev_get_drvdata(dev); - struct device_attribute **attr; + struct pcmcia_socket *s = class_get_devdata(class_dev); + struct class_device_attribute **attr; if (s->resource_ops != &pccard_nonstatic_ops) return; for (attr = pccard_rsrc_attributes; *attr; attr++) - device_remove_file(dev, *attr); + class_device_remove_file(class_dev, *attr); } static struct class_interface pccard_rsrc_interface = { .class = &pcmcia_socket_class, - .add_dev = &pccard_sysfs_add_rsrc, - .remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc), + .add = &pccard_sysfs_add_rsrc, + .remove = __devexit_p(&pccard_sysfs_remove_rsrc), }; static int __init nonstatic_sysfs_init(void) diff --git a/trunk/drivers/pcmcia/soc_common.c b/trunk/drivers/pcmcia/soc_common.c index d2a3bea55de2..e433704e026a 100644 --- a/trunk/drivers/pcmcia/soc_common.c +++ b/trunk/drivers/pcmcia/soc_common.c @@ -478,10 +478,10 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i * * Returns: the number of characters added to the buffer */ -static ssize_t show_status(struct device *dev, char *buf) +static ssize_t show_status(struct class_device *class_dev, char *buf) { struct soc_pcmcia_socket *skt = - container_of(dev, struct soc_pcmcia_socket, socket.dev); + container_of(class_dev, struct soc_pcmcia_socket, socket.dev); char *p = buf; p+=sprintf(p, "slot : %d\n", skt->nr); @@ -747,7 +747,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops add_timer(&skt->poll_timer); - device_create_file(&skt->socket.dev, &device_attr_status); + class_device_create_file(&skt->socket.dev, &class_device_attr_status); } dev_set_drvdata(dev, sinfo); diff --git a/trunk/drivers/pcmcia/socket_sysfs.c b/trunk/drivers/pcmcia/socket_sysfs.c index ea5765c3bdc0..b005602d6b53 100644 --- a/trunk/drivers/pcmcia/socket_sysfs.c +++ b/trunk/drivers/pcmcia/socket_sysfs.c @@ -40,8 +40,7 @@ #define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev) -static ssize_t pccard_show_type(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t pccard_show_type(struct class_device *dev, char *buf) { struct pcmcia_socket *s = to_socket(dev); @@ -51,10 +50,9 @@ static ssize_t pccard_show_type(struct device *dev, struct device_attribute *att return sprintf(buf, "32-bit\n"); return sprintf(buf, "16-bit\n"); } -static DEVICE_ATTR(card_type, 0444, pccard_show_type, NULL); +static CLASS_DEVICE_ATTR(card_type, 0444, pccard_show_type, NULL); -static ssize_t pccard_show_voltage(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t pccard_show_voltage(struct class_device *dev, char *buf) { struct pcmcia_socket *s = to_socket(dev); @@ -65,31 +63,28 @@ static ssize_t pccard_show_voltage(struct device *dev, struct device_attribute * s->socket.Vcc % 10); return sprintf(buf, "X.XV\n"); } -static DEVICE_ATTR(card_voltage, 0444, pccard_show_voltage, NULL); +static CLASS_DEVICE_ATTR(card_voltage, 0444, pccard_show_voltage, NULL); -static ssize_t pccard_show_vpp(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t pccard_show_vpp(struct class_device *dev, char *buf) { struct pcmcia_socket *s = to_socket(dev); if (!(s->state & SOCKET_PRESENT)) return -ENODEV; return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10); } -static DEVICE_ATTR(card_vpp, 0444, pccard_show_vpp, NULL); +static CLASS_DEVICE_ATTR(card_vpp, 0444, pccard_show_vpp, NULL); -static ssize_t pccard_show_vcc(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t pccard_show_vcc(struct class_device *dev, char *buf) { struct pcmcia_socket *s = to_socket(dev); if (!(s->state & SOCKET_PRESENT)) return -ENODEV; return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10); } -static DEVICE_ATTR(card_vcc, 0444, pccard_show_vcc, NULL); +static CLASS_DEVICE_ATTR(card_vcc, 0444, pccard_show_vcc, NULL); -static ssize_t pccard_store_insert(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, size_t count) { ssize_t ret; struct pcmcia_socket *s = to_socket(dev); @@ -101,20 +96,16 @@ static ssize_t pccard_store_insert(struct device *dev, struct device_attribute * return ret ? ret : count; } -static DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert); +static CLASS_DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert); -static ssize_t pccard_show_card_pm_state(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t pccard_show_card_pm_state(struct class_device *dev, char *buf) { struct pcmcia_socket *s = to_socket(dev); return sprintf(buf, "%s\n", s->state & SOCKET_SUSPEND ? "off" : "on"); } -static ssize_t pccard_store_card_pm_state(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pccard_store_card_pm_state(struct class_device *dev, const char *buf, size_t count) { ssize_t ret = -EINVAL; struct pcmcia_socket *s = to_socket(dev); @@ -129,11 +120,9 @@ static ssize_t pccard_store_card_pm_state(struct device *dev, return ret ? -ENODEV : count; } -static DEVICE_ATTR(card_pm_state, 0644, pccard_show_card_pm_state, pccard_store_card_pm_state); +static CLASS_DEVICE_ATTR(card_pm_state, 0644, pccard_show_card_pm_state, pccard_store_card_pm_state); -static ssize_t pccard_store_eject(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pccard_store_eject(struct class_device *dev, const char *buf, size_t count) { ssize_t ret; struct pcmcia_socket *s = to_socket(dev); @@ -145,20 +134,16 @@ static ssize_t pccard_store_eject(struct device *dev, return ret ? ret : count; } -static DEVICE_ATTR(card_eject, 0200, NULL, pccard_store_eject); +static CLASS_DEVICE_ATTR(card_eject, 0200, NULL, pccard_store_eject); -static ssize_t pccard_show_irq_mask(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t pccard_show_irq_mask(struct class_device *dev, char *buf) { struct pcmcia_socket *s = to_socket(dev); return sprintf(buf, "0x%04x\n", s->irq_mask); } -static ssize_t pccard_store_irq_mask(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pccard_store_irq_mask(struct class_device *dev, const char *buf, size_t count) { ssize_t ret; struct pcmcia_socket *s = to_socket(dev); @@ -176,19 +161,16 @@ static ssize_t pccard_store_irq_mask(struct device *dev, return ret ? ret : count; } -static DEVICE_ATTR(card_irq_mask, 0600, pccard_show_irq_mask, pccard_store_irq_mask); +static CLASS_DEVICE_ATTR(card_irq_mask, 0600, pccard_show_irq_mask, pccard_store_irq_mask); -static ssize_t pccard_show_resource(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pccard_show_resource(struct class_device *dev, char *buf) { struct pcmcia_socket *s = to_socket(dev); return sprintf(buf, "%s\n", s->resource_setup_done ? "yes" : "no"); } -static ssize_t pccard_store_resource(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, size_t count) { unsigned long flags; struct pcmcia_socket *s = to_socket(dev); @@ -214,7 +196,7 @@ static ssize_t pccard_store_resource(struct device *dev, return count; } -static DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); +static CLASS_DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off, size_t count) @@ -297,7 +279,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size if (off + count > size) count = size - off; - s = to_socket(container_of(kobj, struct device, kobj)); + s = to_socket(container_of(kobj, struct class_device, kobj)); if (!(s->state & SOCKET_PRESENT)) return -ENODEV; @@ -314,7 +296,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) { - struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); + struct pcmcia_socket *s = to_socket(container_of(kobj, struct class_device, kobj)); cisdump_t *cis; int error; @@ -353,16 +335,16 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz } -static struct device_attribute *pccard_socket_attributes[] = { - &dev_attr_card_type, - &dev_attr_card_voltage, - &dev_attr_card_vpp, - &dev_attr_card_vcc, - &dev_attr_card_insert, - &dev_attr_card_pm_state, - &dev_attr_card_eject, - &dev_attr_card_irq_mask, - &dev_attr_available_resources_setup_done, +static struct class_device_attribute *pccard_socket_attributes[] = { + &class_device_attr_card_type, + &class_device_attr_card_voltage, + &class_device_attr_card_vpp, + &class_device_attr_card_vcc, + &class_device_attr_card_insert, + &class_device_attr_card_pm_state, + &class_device_attr_card_eject, + &class_device_attr_card_irq_mask, + &class_device_attr_available_resources_setup_done, NULL, }; @@ -373,35 +355,35 @@ static struct bin_attribute pccard_cis_attr = { .write = pccard_store_cis, }; -static int __devinit pccard_sysfs_add_socket(struct device *dev, +static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev, struct class_interface *class_intf) { - struct device_attribute **attr; + struct class_device_attribute **attr; int ret = 0; for (attr = pccard_socket_attributes; *attr; attr++) { - ret = device_create_file(dev, *attr); + ret = class_device_create_file(class_dev, *attr); if (ret) break; } if (!ret) - ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr); + ret = sysfs_create_bin_file(&class_dev->kobj, &pccard_cis_attr); return ret; } -static void __devexit pccard_sysfs_remove_socket(struct device *dev, +static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev, struct class_interface *class_intf) { - struct device_attribute **attr; + struct class_device_attribute **attr; - sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr); + sysfs_remove_bin_file(&class_dev->kobj, &pccard_cis_attr); for (attr = pccard_socket_attributes; *attr; attr++) - device_remove_file(dev, *attr); + class_device_remove_file(class_dev, *attr); } struct class_interface pccard_sysfs_interface = { .class = &pcmcia_socket_class, - .add_dev = &pccard_sysfs_add_socket, - .remove_dev = __devexit_p(&pccard_sysfs_remove_socket), + .add = &pccard_sysfs_add_socket, + .remove = __devexit_p(&pccard_sysfs_remove_socket), }; diff --git a/trunk/drivers/pcmcia/tcic.c b/trunk/drivers/pcmcia/tcic.c index c158cf38b9dd..2d2f415f80a8 100644 --- a/trunk/drivers/pcmcia/tcic.c +++ b/trunk/drivers/pcmcia/tcic.c @@ -512,7 +512,7 @@ static int __init init_tcic(void) for (i = 0; i < sockets; i++) { socket_table[i].socket.ops = &tcic_operations; socket_table[i].socket.resource_ops = &pccard_nonstatic_ops; - socket_table[i].socket.dev.parent = &tcic_device.dev; + socket_table[i].socket.dev.dev = &tcic_device.dev; ret = pcmcia_register_socket(&socket_table[i].socket); if (ret && i) pcmcia_unregister_socket(&socket_table[0].socket); diff --git a/trunk/drivers/pcmcia/yenta_socket.c b/trunk/drivers/pcmcia/yenta_socket.c index a61d768f6e0e..da471bddc972 100644 --- a/trunk/drivers/pcmcia/yenta_socket.c +++ b/trunk/drivers/pcmcia/yenta_socket.c @@ -1104,7 +1104,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i /* prepare pcmcia_socket */ socket->socket.ops = ¥ta_socket_operations; socket->socket.resource_ops = &pccard_nonstatic_ops; - socket->socket.dev.parent = &dev->dev; + socket->socket.dev.dev = &dev->dev; socket->socket.driver_data = socket; socket->socket.owner = THIS_MODULE; socket->socket.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD; diff --git a/trunk/drivers/scsi/ipr.c b/trunk/drivers/scsi/ipr.c index 821386c7b576..b318500785e5 100644 --- a/trunk/drivers/scsi/ipr.c +++ b/trunk/drivers/scsi/ipr.c @@ -7558,6 +7558,9 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, diff --git a/trunk/drivers/spi/pxa2xx_spi.c b/trunk/drivers/spi/pxa2xx_spi.c index dccdc50b0296..8b41f9cc2560 100644 --- a/trunk/drivers/spi/pxa2xx_spi.c +++ b/trunk/drivers/spi/pxa2xx_spi.c @@ -1234,7 +1234,7 @@ static int init_queue(struct driver_data *drv_data) INIT_WORK(&drv_data->pump_messages, pump_messages); drv_data->workqueue = create_singlethread_workqueue( - drv_data->master->dev.parent->bus_id); + drv_data->master->cdev.dev->bus_id); if (drv_data->workqueue == NULL) return -EBUSY; diff --git a/trunk/drivers/spi/spi.c b/trunk/drivers/spi/spi.c index 35d8c01b42ac..6307428d2c94 100644 --- a/trunk/drivers/spi/spi.c +++ b/trunk/drivers/spi/spi.c @@ -193,7 +193,7 @@ struct spi_device *__init_or_module spi_new_device(struct spi_master *master, struct spi_board_info *chip) { struct spi_device *proxy; - struct device *dev = &master->dev; + struct device *dev = master->cdev.dev; int status; /* NOTE: caller did any chip->bus_num checks necessary */ @@ -215,7 +215,7 @@ spi_new_device(struct spi_master *master, struct spi_board_info *chip) proxy->modalias = chip->modalias; snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id, - "%s.%u", master->dev.bus_id, + "%s.%u", master->cdev.class_id, chip->chip_select); proxy->dev.parent = dev; proxy->dev.bus = &spi_bus_type; @@ -290,7 +290,7 @@ static void __init_or_module scan_boardinfo(struct spi_master *master) { struct boardinfo *bi; - struct device *dev = master->dev.parent; + struct device *dev = master->cdev.dev; down(&board_lock); list_for_each_entry(bi, &board_list, list) { @@ -319,18 +319,18 @@ scan_boardinfo(struct spi_master *master) /*-------------------------------------------------------------------------*/ -static void spi_master_release(struct device *dev) +static void spi_master_release(struct class_device *cdev) { struct spi_master *master; - master = container_of(dev, struct spi_master, dev); + master = container_of(cdev, struct spi_master, cdev); kfree(master); } static struct class spi_master_class = { .name = "spi_master", .owner = THIS_MODULE, - .dev_release = spi_master_release, + .release = spi_master_release, }; @@ -364,9 +364,9 @@ spi_alloc_master(struct device *dev, unsigned size) if (!master) return NULL; - device_initialize(&master->dev); - master->dev.class = &spi_master_class; - master->dev.parent = get_device(dev); + class_device_initialize(&master->cdev); + master->cdev.class = &spi_master_class; + master->cdev.dev = get_device(dev); spi_master_set_devdata(master, &master[1]); return master; @@ -396,7 +396,7 @@ int __init_or_module spi_register_master(struct spi_master *master) { static atomic_t dyn_bus_id = ATOMIC_INIT((1<<16) - 1); - struct device *dev = master->dev.parent; + struct device *dev = master->cdev.dev; int status = -ENODEV; int dynamic = 0; @@ -412,12 +412,12 @@ spi_register_master(struct spi_master *master) /* register the device, then userspace will see it. * registration fails if the bus ID is in use. */ - snprintf(master->dev.bus_id, sizeof master->dev.bus_id, + snprintf(master->cdev.class_id, sizeof master->cdev.class_id, "spi%u", master->bus_num); - status = device_add(&master->dev); + status = class_device_add(&master->cdev); if (status < 0) goto done; - dev_dbg(dev, "registered master %s%s\n", master->dev.bus_id, + dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id, dynamic ? " (dynamic)" : ""); /* populate children from any spi device tables */ @@ -449,8 +449,8 @@ void spi_unregister_master(struct spi_master *master) { int dummy; - dummy = device_for_each_child(&master->dev, NULL, __unregister); - device_unregister(&master->dev); + dummy = device_for_each_child(master->cdev.dev, NULL, __unregister); + class_device_unregister(&master->cdev); } EXPORT_SYMBOL_GPL(spi_unregister_master); @@ -471,7 +471,7 @@ struct spi_master *spi_busnum_to_master(u16 bus_num) down(&spi_master_class.sem); list_for_each_entry(cdev, &spi_master_class.children, node) { - m = container_of(cdev, struct spi_master, dev.kobj); + m = container_of(cdev, struct spi_master, cdev); if (m->bus_num == bus_num) { master = spi_master_get(m); break; diff --git a/trunk/drivers/spi/spi_bitbang.c b/trunk/drivers/spi/spi_bitbang.c index 4638e6c83715..57289b61d0be 100644 --- a/trunk/drivers/spi/spi_bitbang.c +++ b/trunk/drivers/spi/spi_bitbang.c @@ -479,7 +479,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) /* this task is the only thing to touch the SPI bits */ bitbang->busy = 0; bitbang->workqueue = create_singlethread_workqueue( - bitbang->master->dev.parent->bus_id); + bitbang->master->cdev.dev->bus_id); if (bitbang->workqueue == NULL) { status = -EBUSY; goto err1; @@ -513,14 +513,14 @@ int spi_bitbang_stop(struct spi_bitbang *bitbang) while (!list_empty(&bitbang->queue) && limit--) { spin_unlock_irq(&bitbang->lock); - dev_dbg(&bitbang->master->dev, "wait for queue\n"); + dev_dbg(bitbang->master->cdev.dev, "wait for queue\n"); msleep(10); spin_lock_irq(&bitbang->lock); } spin_unlock_irq(&bitbang->lock); if (!list_empty(&bitbang->queue)) { - dev_err(&bitbang->master->dev, "queue didn't empty\n"); + dev_err(bitbang->master->cdev.dev, "queue didn't empty\n"); return -EBUSY; } diff --git a/trunk/drivers/spi/spi_butterfly.c b/trunk/drivers/spi/spi_butterfly.c index 31b7970ae463..312987a03210 100644 --- a/trunk/drivers/spi/spi_butterfly.c +++ b/trunk/drivers/spi/spi_butterfly.c @@ -246,7 +246,7 @@ static void butterfly_attach(struct parport *p) * and no way to be selective about what it binds to. */ - /* FIXME where should master->dev.parent come from? + /* FIXME where should master->cdev.dev come from? * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc * setting up a platform device like this is an ugly kluge... */ @@ -386,7 +386,7 @@ static void butterfly_detach(struct parport *p) butterfly = NULL; /* stop() unregisters child devices too */ - pdev = to_platform_device(pp->bitbang.master->dev.parent); + pdev = to_platform_device(pp->bitbang.master->cdev.dev); status = spi_bitbang_stop(&pp->bitbang); /* turn off VCC */ diff --git a/trunk/drivers/usb/atm/speedtch.c b/trunk/drivers/usb/atm/speedtch.c index 638b8009b3bc..8ed6c75adf0f 100644 --- a/trunk/drivers/usb/atm/speedtch.c +++ b/trunk/drivers/usb/atm/speedtch.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include "usbatm.h" diff --git a/trunk/drivers/usb/class/usblp.c b/trunk/drivers/usb/class/usblp.c index 63e50a1f1396..6377db1b446d 100644 --- a/trunk/drivers/usb/class/usblp.c +++ b/trunk/drivers/usb/class/usblp.c @@ -398,9 +398,6 @@ static int usblp_open(struct inode *inode, struct file *file) retval = 0; #endif - retval = usb_autopm_get_interface(intf); - if (retval < 0) - goto out; usblp->used = 1; file->private_data = usblp; @@ -445,7 +442,6 @@ static int usblp_release(struct inode *inode, struct file *file) usblp->used = 0; if (usblp->present) { usblp_unlink_urbs(usblp); - usb_autopm_put_interface(usblp->intf); } else /* finish cleanup from disconnect */ usblp_cleanup (usblp); mutex_unlock (&usblp_mutex); @@ -1207,9 +1203,14 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message) { struct usblp *usblp = usb_get_intfdata (intf); + /* this races against normal access and open */ + mutex_lock (&usblp_mutex); + mutex_lock (&usblp->mut); /* we take no more IO */ usblp->sleeping = 1; usblp_unlink_urbs(usblp); + mutex_unlock (&usblp->mut); + mutex_unlock (&usblp_mutex); return 0; } @@ -1219,9 +1220,15 @@ static int usblp_resume (struct usb_interface *intf) struct usblp *usblp = usb_get_intfdata (intf); int r; + mutex_lock (&usblp_mutex); + mutex_lock (&usblp->mut); + usblp->sleeping = 0; r = handle_bidir (usblp); + mutex_unlock (&usblp->mut); + mutex_unlock (&usblp_mutex); + return r; } @@ -1244,7 +1251,6 @@ static struct usb_driver usblp_driver = { .suspend = usblp_suspend, .resume = usblp_resume, .id_table = usblp_ids, - .supports_autosuspend = 1, }; static int __init usblp_init(void) diff --git a/trunk/drivers/usb/core/Kconfig b/trunk/drivers/usb/core/Kconfig index 2fc0f88a3d86..3e66b2a9974a 100644 --- a/trunk/drivers/usb/core/Kconfig +++ b/trunk/drivers/usb/core/Kconfig @@ -33,6 +33,19 @@ config USB_DEVICEFS Most users want to say Y here. +config USB_BANDWIDTH + bool "Enforce USB bandwidth allocation (EXPERIMENTAL)" + depends on USB && EXPERIMENTAL + help + If you say Y here, the USB subsystem enforces USB bandwidth + allocation and will prevent some device opens from succeeding + if they would cause USB bandwidth usage to go above 90% of + the bus bandwidth. + + If you say N here, these conditions will cause warning messages + about USB bandwidth usage to be logged and some devices or + drivers may not work correctly. + config USB_DYNAMIC_MINORS bool "Dynamic USB minor allocation (EXPERIMENTAL)" depends on USB && EXPERIMENTAL diff --git a/trunk/drivers/usb/core/buffer.c b/trunk/drivers/usb/core/buffer.c index ead2475406b8..c3915dc28608 100644 --- a/trunk/drivers/usb/core/buffer.c +++ b/trunk/drivers/usb/core/buffer.c @@ -49,9 +49,9 @@ static const size_t pool_max [HCD_BUFFER_POOLS] = { * * Call hcd_buffer_destroy() to clean up after using those pools. */ -int hcd_buffer_create(struct usb_hcd *hcd) +int hcd_buffer_create (struct usb_hcd *hcd) { - char name[16]; + char name [16]; int i, size; if (!hcd->self.controller->dma_mask) @@ -60,11 +60,11 @@ int hcd_buffer_create(struct usb_hcd *hcd) for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (!(size = pool_max [i])) continue; - snprintf(name, sizeof name, "buffer-%d", size); - hcd->pool[i] = dma_pool_create(name, hcd->self.controller, + snprintf (name, sizeof name, "buffer-%d", size); + hcd->pool [i] = dma_pool_create (name, hcd->self.controller, size, size, 0); if (!hcd->pool [i]) { - hcd_buffer_destroy(hcd); + hcd_buffer_destroy (hcd); return -ENOMEM; } } @@ -79,14 +79,14 @@ int hcd_buffer_create(struct usb_hcd *hcd) * * This frees the buffer pools created by hcd_buffer_create(). */ -void hcd_buffer_destroy(struct usb_hcd *hcd) +void hcd_buffer_destroy (struct usb_hcd *hcd) { int i; for (i = 0; i < HCD_BUFFER_POOLS; i++) { - struct dma_pool *pool = hcd->pool[i]; + struct dma_pool *pool = hcd->pool [i]; if (pool) { - dma_pool_destroy(pool); + dma_pool_destroy (pool); hcd->pool[i] = NULL; } } @@ -97,8 +97,8 @@ void hcd_buffer_destroy(struct usb_hcd *hcd) * better sharing and to leverage mm/slab.c intelligence. */ -void *hcd_buffer_alloc( - struct usb_bus *bus, +void *hcd_buffer_alloc ( + struct usb_bus *bus, size_t size, gfp_t mem_flags, dma_addr_t *dma @@ -110,18 +110,18 @@ void *hcd_buffer_alloc( /* some USB hosts just use PIO */ if (!bus->controller->dma_mask) { *dma = ~(dma_addr_t) 0; - return kmalloc(size, mem_flags); + return kmalloc (size, mem_flags); } for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max [i]) - return dma_pool_alloc(hcd->pool [i], mem_flags, dma); + return dma_pool_alloc (hcd->pool [i], mem_flags, dma); } - return dma_alloc_coherent(hcd->self.controller, size, dma, 0); + return dma_alloc_coherent (hcd->self.controller, size, dma, 0); } -void hcd_buffer_free( - struct usb_bus *bus, +void hcd_buffer_free ( + struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma @@ -134,15 +134,15 @@ void hcd_buffer_free( return; if (!bus->controller->dma_mask) { - kfree(addr); + kfree (addr); return; } for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max [i]) { - dma_pool_free(hcd->pool [i], addr, dma); + dma_pool_free (hcd->pool [i], addr, dma); return; } } - dma_free_coherent(hcd->self.controller, size, addr, dma); + dma_free_coherent (hcd->self.controller, size, addr, dma); } diff --git a/trunk/drivers/usb/core/devices.c b/trunk/drivers/usb/core/devices.c index a47c30b2d764..ea398e5d50af 100644 --- a/trunk/drivers/usb/core/devices.c +++ b/trunk/drivers/usb/core/devices.c @@ -104,7 +104,7 @@ static const char *format_config = static const char *format_iface = /* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/ - "I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n"; + "I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n"; static const char *format_endpt = /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */ @@ -164,10 +164,10 @@ static const char *class_decode(const int class) for (ix = 0; clas_info[ix].class != -1; ix++) if (clas_info[ix].class == class) break; - return clas_info[ix].class_name; + return (clas_info[ix].class_name); } -static char *usb_dump_endpoint_descriptor( +static char *usb_dump_endpoint_descriptor ( int speed, char *start, char *end, @@ -212,9 +212,9 @@ static char *usb_dump_endpoint_descriptor( break; case USB_ENDPOINT_XFER_INT: type = "Int."; - if (speed == USB_SPEED_HIGH) + if (speed == USB_SPEED_HIGH) { interval = 1 << (desc->bInterval - 1); - else + } else interval = desc->bInterval; break; default: /* "can't happen" */ @@ -242,19 +242,15 @@ static char *usb_dump_interface_descriptor(char *start, char *end, { const struct usb_interface_descriptor *desc = &intfc->altsetting[setno].desc; const char *driver_name = ""; - int active = 0; if (start > end) return start; down_read(&usb_bus_type.subsys.rwsem); - if (iface) { + if (iface) driver_name = (iface->dev.driver ? iface->dev.driver->name : "(none)"); - active = (desc == &iface->cur_altsetting->desc); - } start += sprintf(start, format_iface, - active ? '*' : ' ', /* mark active altsetting */ desc->bInterfaceNumber, desc->bAlternateSetting, desc->bNumEndpoints, @@ -347,7 +343,7 @@ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb if (start > end) return start; - start += sprintf(start, format_device1, + start += sprintf (start, format_device1, bcdUSB >> 8, bcdUSB & 0xff, desc->bDeviceClass, class_decode (desc->bDeviceClass), @@ -367,7 +363,7 @@ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb /* * Dump the different strings that this device holds. */ -static char *usb_dump_device_strings(char *start, char *end, struct usb_device *dev) +static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev) { if (start > end) return start; @@ -399,7 +395,7 @@ static char *usb_dump_desc(char *start, char *end, struct usb_device *dev) if (start > end) return start; - start = usb_dump_device_strings(start, end, dev); + start = usb_dump_device_strings (start, end, dev); for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { if (start > end) diff --git a/trunk/drivers/usb/core/devio.c b/trunk/drivers/usb/core/devio.c index 2087766f9e88..4b3a6ab29bd3 100644 --- a/trunk/drivers/usb/core/devio.c +++ b/trunk/drivers/usb/core/devio.c @@ -522,19 +522,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig static struct usb_device *usbdev_lookup_minor(int minor) { - struct device *device; - struct usb_device *udev = NULL; + struct class_device *class_dev; + struct usb_device *dev = NULL; down(&usb_device_class->sem); - list_for_each_entry(device, &usb_device_class->devices, node) { - if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { - udev = device->platform_data; + list_for_each_entry(class_dev, &usb_device_class->children, node) { + if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { + dev = class_dev->class_data; break; } } up(&usb_device_class->sem); - return udev; + return dev; }; /* @@ -570,7 +570,6 @@ static int usbdev_open(struct inode *inode, struct file *file) ps->dev = dev; ps->file = file; spin_lock_init(&ps->lock); - INIT_LIST_HEAD(&ps->list); INIT_LIST_HEAD(&ps->async_pending); INIT_LIST_HEAD(&ps->async_completed); init_waitqueue_head(&ps->wait); @@ -1597,19 +1596,19 @@ static int usbdev_add(struct usb_device *dev) { int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); - dev->usbfs_dev = device_create(usb_device_class, &dev->dev, - MKDEV(USB_DEVICE_MAJOR, minor), + dev->class_dev = class_device_create(usb_device_class, NULL, + MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, "usbdev%d.%d", dev->bus->busnum, dev->devnum); - if (IS_ERR(dev->usbfs_dev)) - return PTR_ERR(dev->usbfs_dev); + if (IS_ERR(dev->class_dev)) + return PTR_ERR(dev->class_dev); - dev->usbfs_dev->platform_data = dev; + dev->class_dev->class_data = dev; return 0; } static void usbdev_remove(struct usb_device *dev) { - device_unregister(dev->usbfs_dev); + class_device_unregister(dev->class_dev); } static int usbdev_notify(struct notifier_block *self, unsigned long action, diff --git a/trunk/drivers/usb/core/driver.c b/trunk/drivers/usb/core/driver.c index 600d1bc8272a..d6eb5ce1dd1d 100644 --- a/trunk/drivers/usb/core/driver.c +++ b/trunk/drivers/usb/core/driver.c @@ -28,16 +28,24 @@ #include "hcd.h" #include "usb.h" +static int usb_match_one_id(struct usb_interface *interface, + const struct usb_device_id *id); + +struct usb_dynid { + struct list_head node; + struct usb_device_id id; +}; + #ifdef CONFIG_HOTPLUG /* * Adds a new dynamic USBdevice ID to this driver, * and cause the driver to probe for all devices again. */ -ssize_t usb_store_new_id(struct usb_dynids *dynids, - struct device_driver *driver, - const char *buf, size_t count) +static ssize_t store_new_id(struct device_driver *driver, + const char *buf, size_t count) { + struct usb_driver *usb_drv = to_usb_driver(driver); struct usb_dynid *dynid; u32 idVendor = 0; u32 idProduct = 0; @@ -57,9 +65,9 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, dynid->id.idProduct = idProduct; dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE; - spin_lock(&dynids->lock); - list_add_tail(&dynids->list, &dynid->node); - spin_unlock(&dynids->lock); + spin_lock(&usb_drv->dynids.lock); + list_add_tail(&usb_drv->dynids.list, &dynid->node); + spin_unlock(&usb_drv->dynids.lock); if (get_driver(driver)) { retval = driver_attach(driver); @@ -70,15 +78,6 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, return retval; return count; } -EXPORT_SYMBOL_GPL(usb_store_new_id); - -static ssize_t store_new_id(struct device_driver *driver, - const char *buf, size_t count) -{ - struct usb_driver *usb_drv = to_usb_driver(driver); - - return usb_store_new_id(&usb_drv->dynids, driver, buf, count); -} static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); static int usb_create_newid_file(struct usb_driver *usb_drv) @@ -366,8 +365,8 @@ void usb_driver_release_interface(struct usb_driver *driver, EXPORT_SYMBOL(usb_driver_release_interface); /* returns 0 if no match, 1 if match */ -int usb_match_one_id(struct usb_interface *interface, - const struct usb_device_id *id) +static int usb_match_one_id(struct usb_interface *interface, + const struct usb_device_id *id) { struct usb_host_interface *intf; struct usb_device *dev; @@ -433,8 +432,6 @@ int usb_match_one_id(struct usb_interface *interface, return 1; } -EXPORT_SYMBOL_GPL(usb_match_one_id); - /** * usb_match_id - find first usb_device_id matching device or interface * @interface: the interface of interest @@ -753,8 +750,7 @@ EXPORT_SYMBOL_GPL(usb_deregister_device_driver); * usb_register_dev() to enable that functionality. This function no longer * takes care of that. */ -int usb_register_driver(struct usb_driver *new_driver, struct module *owner, - const char *mod_name) +int usb_register_driver(struct usb_driver *new_driver, struct module *owner) { int retval = 0; @@ -767,7 +763,6 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, new_driver->drvwrap.driver.probe = usb_probe_interface; new_driver->drvwrap.driver.remove = usb_unbind_interface; new_driver->drvwrap.driver.owner = owner; - new_driver->drvwrap.driver.mod_name = mod_name; spin_lock_init(&new_driver->dynids.lock); INIT_LIST_HEAD(&new_driver->dynids.list); diff --git a/trunk/drivers/usb/core/file.c b/trunk/drivers/usb/core/file.c index 01c857ac27af..f794f07cfb33 100644 --- a/trunk/drivers/usb/core/file.c +++ b/trunk/drivers/usb/core/file.c @@ -194,13 +194,14 @@ int usb_register_dev(struct usb_interface *intf, ++temp; else temp = name; - intf->usb_dev = device_create(usb_class->class, &intf->dev, - MKDEV(USB_MAJOR, minor), "%s", temp); - if (IS_ERR(intf->usb_dev)) { + intf->class_dev = class_device_create(usb_class->class, NULL, + MKDEV(USB_MAJOR, minor), + &intf->dev, "%s", temp); + if (IS_ERR(intf->class_dev)) { spin_lock (&minor_lock); usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); - retval = PTR_ERR(intf->usb_dev); + retval = PTR_ERR(intf->class_dev); } exit: return retval; @@ -241,8 +242,8 @@ void usb_deregister_dev(struct usb_interface *intf, spin_unlock (&minor_lock); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); - device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); - intf->usb_dev = NULL; + class_device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); + intf->class_dev = NULL; intf->minor = -1; destroy_usb_class(); } diff --git a/trunk/drivers/usb/core/generic.c b/trunk/drivers/usb/core/generic.c index b531a4fd30c2..ebb20ff7ac58 100644 --- a/trunk/drivers/usb/core/generic.c +++ b/trunk/drivers/usb/core/generic.c @@ -25,20 +25,6 @@ static inline const char *plural(int n) return (n == 1 ? "" : "s"); } -static int is_rndis(struct usb_interface_descriptor *desc) -{ - return desc->bInterfaceClass == USB_CLASS_COMM - && desc->bInterfaceSubClass == 2 - && desc->bInterfaceProtocol == 0xff; -} - -static int is_activesync(struct usb_interface_descriptor *desc) -{ - return desc->bInterfaceClass == USB_CLASS_MISC - && desc->bInterfaceSubClass == 1 - && desc->bInterfaceProtocol == 1; -} - static int choose_configuration(struct usb_device *udev) { int i; @@ -101,12 +87,14 @@ static int choose_configuration(struct usb_device *udev) continue; } - /* When the first config's first interface is one of Microsoft's - * pet nonstandard Ethernet-over-USB protocols, ignore it unless - * this kernel has enabled the necessary host side driver. - */ - if (i == 0 && desc && (is_rndis(desc) || is_activesync(desc))) { -#if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE) + /* If the first config's first interface is COMM/2/0xff + * (MSFT RNDIS), rule it out unless Linux has host-side + * RNDIS support. */ + if (i == 0 && desc + && desc->bInterfaceClass == USB_CLASS_COMM + && desc->bInterfaceSubClass == 2 + && desc->bInterfaceProtocol == 0xff) { +#ifndef CONFIG_USB_NET_RNDIS_HOST continue; #else best = c; diff --git a/trunk/drivers/usb/core/hcd.c b/trunk/drivers/usb/core/hcd.c index b26c19e8d19f..10064af65d17 100644 --- a/trunk/drivers/usb/core/hcd.c +++ b/trunk/drivers/usb/core/hcd.c @@ -45,6 +45,8 @@ #include "hub.h" +// #define USB_BANDWIDTH_MESSAGES + /*-------------------------------------------------------------------------*/ /* @@ -889,6 +891,136 @@ long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount) } EXPORT_SYMBOL (usb_calc_bus_time); +/* + * usb_check_bandwidth(): + * + * old_alloc is from host_controller->bandwidth_allocated in microseconds; + * bustime is from calc_bus_time(), but converted to microseconds. + * + * returns if successful, + * or -ENOSPC if bandwidth request fails. + * + * FIXME: + * This initial implementation does not use Endpoint.bInterval + * in managing bandwidth allocation. + * It probably needs to be expanded to use Endpoint.bInterval. + * This can be done as a later enhancement (correction). + * + * This will also probably require some kind of + * frame allocation tracking...meaning, for example, + * that if multiple drivers request interrupts every 10 USB frames, + * they don't all have to be allocated at + * frame numbers N, N+10, N+20, etc. Some of them could be at + * N+11, N+21, N+31, etc., and others at + * N+12, N+22, N+32, etc. + * + * Similarly for isochronous transfers... + * + * Individual HCDs can schedule more directly ... this logic + * is not correct for high speed transfers. + */ +int usb_check_bandwidth (struct usb_device *dev, struct urb *urb) +{ + unsigned int pipe = urb->pipe; + long bustime; + int is_in = usb_pipein (pipe); + int is_iso = usb_pipeisoc (pipe); + int old_alloc = dev->bus->bandwidth_allocated; + int new_alloc; + + + bustime = NS_TO_US (usb_calc_bus_time (dev->speed, is_in, is_iso, + usb_maxpacket (dev, pipe, !is_in))); + if (is_iso) + bustime /= urb->number_of_packets; + + new_alloc = old_alloc + (int) bustime; + if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC) { +#ifdef DEBUG + char *mode = +#ifdef CONFIG_USB_BANDWIDTH + ""; +#else + "would have "; +#endif + dev_dbg (&dev->dev, "usb_check_bandwidth %sFAILED: %d + %ld = %d usec\n", + mode, old_alloc, bustime, new_alloc); +#endif +#ifdef CONFIG_USB_BANDWIDTH + bustime = -ENOSPC; /* report error */ +#endif + } + + return bustime; +} +EXPORT_SYMBOL (usb_check_bandwidth); + + +/** + * usb_claim_bandwidth - records bandwidth for a periodic transfer + * @dev: source/target of request + * @urb: request (urb->dev == dev) + * @bustime: bandwidth consumed, in (average) microseconds per frame + * @isoc: true iff the request is isochronous + * + * Bus bandwidth reservations are recorded purely for diagnostic purposes. + * HCDs are expected not to overcommit periodic bandwidth, and to record such + * reservations whenever endpoints are added to the periodic schedule. + * + * FIXME averaging per-frame is suboptimal. Better to sum over the HCD's + * entire periodic schedule ... 32 frames for OHCI, 1024 for UHCI, settable + * for EHCI (256/512/1024 frames, default 1024) and have the bus expose how + * large its periodic schedule is. + */ +void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc) +{ + dev->bus->bandwidth_allocated += bustime; + if (isoc) + dev->bus->bandwidth_isoc_reqs++; + else + dev->bus->bandwidth_int_reqs++; + urb->bandwidth = bustime; + +#ifdef USB_BANDWIDTH_MESSAGES + dev_dbg (&dev->dev, "bandwidth alloc increased by %d (%s) to %d for %d requesters\n", + bustime, + isoc ? "ISOC" : "INTR", + dev->bus->bandwidth_allocated, + dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); +#endif +} +EXPORT_SYMBOL (usb_claim_bandwidth); + + +/** + * usb_release_bandwidth - reverses effect of usb_claim_bandwidth() + * @dev: source/target of request + * @urb: request (urb->dev == dev) + * @isoc: true iff the request is isochronous + * + * This records that previously allocated bandwidth has been released. + * Bandwidth is released when endpoints are removed from the host controller's + * periodic schedule. + */ +void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, int isoc) +{ + dev->bus->bandwidth_allocated -= urb->bandwidth; + if (isoc) + dev->bus->bandwidth_isoc_reqs--; + else + dev->bus->bandwidth_int_reqs--; + +#ifdef USB_BANDWIDTH_MESSAGES + dev_dbg (&dev->dev, "bandwidth alloc reduced by %d (%s) to %d for %d requesters\n", + urb->bandwidth, + isoc ? "ISOC" : "INTR", + dev->bus->bandwidth_allocated, + dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); +#endif + urb->bandwidth = 0; +} +EXPORT_SYMBOL (usb_release_bandwidth); + /*-------------------------------------------------------------------------*/ @@ -902,6 +1034,11 @@ static void urb_unlink (struct urb *urb) { unsigned long flags; + /* Release any periodic transfer bandwidth */ + if (urb->bandwidth) + usb_release_bandwidth (urb->dev, urb, + usb_pipeisoc (urb->pipe)); + /* clear all state linking urb to this dev (and hcd) */ spin_lock_irqsave (&hcd_data_lock, flags); diff --git a/trunk/drivers/usb/core/hcd.h b/trunk/drivers/usb/core/hcd.h index 2a269ca20517..8f8df0d4382e 100644 --- a/trunk/drivers/usb/core/hcd.h +++ b/trunk/drivers/usb/core/hcd.h @@ -308,6 +308,10 @@ extern void usb_destroy_configuration(struct usb_device *dev); #define NS_TO_US(ns) ((ns + 500L) / 1000L) /* convert & round nanoseconds to microseconds */ +extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, + int bustime, int isoc); +extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, + int isoc); /* * Full/low speed bandwidth allocation constants/support. @@ -320,6 +324,8 @@ extern void usb_destroy_configuration(struct usb_device *dev); #define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) #define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) +extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb); + /* * Ceiling [nano/micro]seconds (typical) for that many bytes at high speed * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed diff --git a/trunk/drivers/usb/core/hub.c b/trunk/drivers/usb/core/hub.c index 590ec82d0515..1988224b362b 100644 --- a/trunk/drivers/usb/core/hub.c +++ b/trunk/drivers/usb/core/hub.c @@ -87,6 +87,9 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); static struct task_struct *khubd_task; +/* multithreaded probe logic */ +static int multithread_probe = 0; + /* cycle leds on hubs that aren't blinking for attention */ static int blinkenlights = 0; module_param (blinkenlights, bool, S_IRUGO); @@ -1253,28 +1256,9 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) static int __usb_port_suspend(struct usb_device *, int port1); #endif -/** - * usb_new_device - perform initial device setup (usbcore-internal) - * @udev: newly addressed device (in ADDRESS state) - * - * This is called with devices which have been enumerated, but not yet - * configured. The device descriptor is available, but not descriptors - * for any device configuration. The caller must have locked either - * the parent hub (if udev is a normal device) or else the - * usb_bus_list_lock (if udev is a root hub). The parent's pointer to - * udev has already been installed, but udev is not yet visible through - * sysfs or other filesystem code. - * - * It will return if the device is configured properly or not. Zero if - * the interface was registered with the driver core; else a negative - * errno value. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Only the hub driver or root-hub registrar should ever call this. - */ -int usb_new_device(struct usb_device *udev) +static int __usb_new_device(void *void_data) { + struct usb_device *udev = void_data; int err; /* Lock ourself into memory in order to keep a probe sequence @@ -1391,6 +1375,44 @@ int usb_new_device(struct usb_device *udev) goto exit; } +/** + * usb_new_device - perform initial device setup (usbcore-internal) + * @udev: newly addressed device (in ADDRESS state) + * + * This is called with devices which have been enumerated, but not yet + * configured. The device descriptor is available, but not descriptors + * for any device configuration. The caller must have locked either + * the parent hub (if udev is a normal device) or else the + * usb_bus_list_lock (if udev is a root hub). The parent's pointer to + * udev has already been installed, but udev is not yet visible through + * sysfs or other filesystem code. + * + * The return value for this function depends on if the + * multithread_probe variable is set or not. If it's set, it will + * return a if the probe thread was successfully created or not. If the + * variable is not set, it will return if the device is configured + * properly or not. interfaces, in sysfs); else a negative errno value. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Only the hub driver or root-hub registrar should ever call this. + */ +int usb_new_device(struct usb_device *udev) +{ + struct task_struct *probe_task; + int ret = 0; + + if (multithread_probe) { + probe_task = kthread_run(__usb_new_device, udev, + "usb-probe-%s", udev->devnum); + if (IS_ERR(probe_task)) + ret = PTR_ERR(probe_task); + } else + ret = __usb_new_device(udev); + + return ret; +} + static int hub_port_status(struct usb_hub *hub, int port1, u16 *status, u16 *change) { diff --git a/trunk/drivers/usb/core/message.c b/trunk/drivers/usb/core/message.c index 8aca3574c2b5..149aa8bfb1fe 100644 --- a/trunk/drivers/usb/core/message.c +++ b/trunk/drivers/usb/core/message.c @@ -1545,7 +1545,11 @@ int usb_driver_set_configuration(struct usb_device *udev, int config) INIT_WORK(&req->work, driver_set_config_work); usb_get_dev(udev); - schedule_work(&req->work); + if (!schedule_work(&req->work)) { + usb_put_dev(udev); + kfree(req); + return -EINVAL; + } return 0; } EXPORT_SYMBOL_GPL(usb_driver_set_configuration); diff --git a/trunk/drivers/usb/core/sysfs.c b/trunk/drivers/usb/core/sysfs.c index 4eaa0ee8e72f..55d8f575206d 100644 --- a/trunk/drivers/usb/core/sysfs.c +++ b/trunk/drivers/usb/core/sysfs.c @@ -16,16 +16,16 @@ /* Active configuration fields */ #define usb_actconfig_show(field, multiplier, format_string) \ -static ssize_t show_##field(struct device *dev, \ +static ssize_t show_##field (struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ struct usb_device *udev; \ struct usb_host_config *actconfig; \ \ - udev = to_usb_device(dev); \ + udev = to_usb_device (dev); \ actconfig = udev->actconfig; \ if (actconfig) \ - return sprintf(buf, format_string, \ + return sprintf (buf, format_string, \ actconfig->desc.field * multiplier); \ else \ return 0; \ @@ -35,9 +35,9 @@ static ssize_t show_##field(struct device *dev, \ usb_actconfig_show(field, multiplier, format_string) \ static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); -usb_actconfig_attr(bNumInterfaces, 1, "%2d\n") -usb_actconfig_attr(bmAttributes, 1, "%2x\n") -usb_actconfig_attr(bMaxPower, 2, "%3dmA\n") +usb_actconfig_attr (bNumInterfaces, 1, "%2d\n") +usb_actconfig_attr (bmAttributes, 1, "%2x\n") +usb_actconfig_attr (bMaxPower, 2, "%3dmA\n") static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf) @@ -45,7 +45,7 @@ static ssize_t show_configuration_string(struct device *dev, struct usb_device *udev; struct usb_host_config *actconfig; - udev = to_usb_device(dev); + udev = to_usb_device (dev); actconfig = udev->actconfig; if ((!actconfig) || (!actconfig->string)) return 0; @@ -57,16 +57,16 @@ static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); usb_actconfig_show(bConfigurationValue, 1, "%u\n"); static ssize_t -set_bConfigurationValue(struct device *dev, struct device_attribute *attr, +set_bConfigurationValue (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct usb_device *udev = to_usb_device(dev); + struct usb_device *udev = to_usb_device (dev); int config, value; - if (sscanf(buf, "%u", &config) != 1 || config > 255) + if (sscanf (buf, "%u", &config) != 1 || config > 255) return -EINVAL; usb_lock_device(udev); - value = usb_set_configuration(udev, config); + value = usb_set_configuration (udev, config); usb_unlock_device(udev); return (value < 0) ? value : count; } @@ -81,7 +81,7 @@ static ssize_t show_##name(struct device *dev, \ { \ struct usb_device *udev; \ \ - udev = to_usb_device(dev); \ + udev = to_usb_device (dev); \ return sprintf(buf, "%s\n", udev->name); \ } \ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); @@ -91,12 +91,12 @@ usb_string_attr(manufacturer); usb_string_attr(serial); static ssize_t -show_speed(struct device *dev, struct device_attribute *attr, char *buf) +show_speed (struct device *dev, struct device_attribute *attr, char *buf) { struct usb_device *udev; char *speed; - udev = to_usb_device(dev); + udev = to_usb_device (dev); switch (udev->speed) { case USB_SPEED_LOW: @@ -112,22 +112,22 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf) default: speed = "unknown"; } - return sprintf(buf, "%s\n", speed); + return sprintf (buf, "%s\n", speed); } static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL); static ssize_t -show_devnum(struct device *dev, struct device_attribute *attr, char *buf) +show_devnum (struct device *dev, struct device_attribute *attr, char *buf) { struct usb_device *udev; - udev = to_usb_device(dev); - return sprintf(buf, "%d\n", udev->devnum); + udev = to_usb_device (dev); + return sprintf (buf, "%d\n", udev->devnum); } static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL); static ssize_t -show_version(struct device *dev, struct device_attribute *attr, char *buf) +show_version (struct device *dev, struct device_attribute *attr, char *buf) { struct usb_device *udev; u16 bcdUSB; @@ -139,25 +139,25 @@ show_version(struct device *dev, struct device_attribute *attr, char *buf) static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); static ssize_t -show_maxchild(struct device *dev, struct device_attribute *attr, char *buf) +show_maxchild (struct device *dev, struct device_attribute *attr, char *buf) { struct usb_device *udev; - udev = to_usb_device(dev); - return sprintf(buf, "%d\n", udev->maxchild); + udev = to_usb_device (dev); + return sprintf (buf, "%d\n", udev->maxchild); } static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL); /* Descriptor fields */ #define usb_descriptor_attr_le16(field, format_string) \ static ssize_t \ -show_##field(struct device *dev, struct device_attribute *attr, \ +show_##field (struct device *dev, struct device_attribute *attr, \ char *buf) \ { \ struct usb_device *udev; \ \ - udev = to_usb_device(dev); \ - return sprintf(buf, format_string, \ + udev = to_usb_device (dev); \ + return sprintf (buf, format_string, \ le16_to_cpu(udev->descriptor.field)); \ } \ static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); @@ -168,21 +168,21 @@ usb_descriptor_attr_le16(bcdDevice, "%04x\n") #define usb_descriptor_attr(field, format_string) \ static ssize_t \ -show_##field(struct device *dev, struct device_attribute *attr, \ +show_##field (struct device *dev, struct device_attribute *attr, \ char *buf) \ { \ struct usb_device *udev; \ \ - udev = to_usb_device(dev); \ - return sprintf(buf, format_string, udev->descriptor.field); \ + udev = to_usb_device (dev); \ + return sprintf (buf, format_string, udev->descriptor.field); \ } \ static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); -usb_descriptor_attr(bDeviceClass, "%02x\n") -usb_descriptor_attr(bDeviceSubClass, "%02x\n") -usb_descriptor_attr(bDeviceProtocol, "%02x\n") -usb_descriptor_attr(bNumConfigurations, "%d\n") -usb_descriptor_attr(bMaxPacketSize0, "%d\n") +usb_descriptor_attr (bDeviceClass, "%02x\n") +usb_descriptor_attr (bDeviceSubClass, "%02x\n") +usb_descriptor_attr (bDeviceProtocol, "%02x\n") +usb_descriptor_attr (bNumConfigurations, "%d\n") +usb_descriptor_attr (bMaxPacketSize0, "%d\n") static struct attribute *dev_attrs[] = { /* current configuration's attributes */ @@ -220,17 +220,17 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) return retval; if (udev->manufacturer) { - retval = device_create_file(dev, &dev_attr_manufacturer); + retval = device_create_file (dev, &dev_attr_manufacturer); if (retval) goto error; } if (udev->product) { - retval = device_create_file(dev, &dev_attr_product); + retval = device_create_file (dev, &dev_attr_product); if (retval) goto error; } if (udev->serial) { - retval = device_create_file(dev, &dev_attr_serial); + retval = device_create_file (dev, &dev_attr_serial); if (retval) goto error; } @@ -246,7 +246,7 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) return retval; } -void usb_remove_sysfs_dev_files(struct usb_device *udev) +void usb_remove_sysfs_dev_files (struct usb_device *udev) { struct device *dev = &udev->dev; @@ -264,22 +264,22 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) /* Interface fields */ #define usb_intf_attr(field, format_string) \ static ssize_t \ -show_##field(struct device *dev, struct device_attribute *attr, \ +show_##field (struct device *dev, struct device_attribute *attr, \ char *buf) \ { \ - struct usb_interface *intf = to_usb_interface(dev); \ + struct usb_interface *intf = to_usb_interface (dev); \ \ - return sprintf(buf, format_string, \ + return sprintf (buf, format_string, \ intf->cur_altsetting->desc.field); \ } \ static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); -usb_intf_attr(bInterfaceNumber, "%02x\n") -usb_intf_attr(bAlternateSetting, "%2d\n") -usb_intf_attr(bNumEndpoints, "%02x\n") -usb_intf_attr(bInterfaceClass, "%02x\n") -usb_intf_attr(bInterfaceSubClass, "%02x\n") -usb_intf_attr(bInterfaceProtocol, "%02x\n") +usb_intf_attr (bInterfaceNumber, "%02x\n") +usb_intf_attr (bAlternateSetting, "%2d\n") +usb_intf_attr (bNumEndpoints, "%02x\n") +usb_intf_attr (bInterfaceClass, "%02x\n") +usb_intf_attr (bInterfaceSubClass, "%02x\n") +usb_intf_attr (bInterfaceProtocol, "%02x\n") static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf) @@ -288,8 +288,8 @@ static ssize_t show_interface_string(struct device *dev, struct usb_device *udev; int len; - intf = to_usb_interface(dev); - udev = interface_to_usbdev(intf); + intf = to_usb_interface (dev); + udev = interface_to_usbdev (intf); len = snprintf(buf, 256, "%s", intf->cur_altsetting->string); if (len < 0) return 0; @@ -384,7 +384,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) return retval; } -void usb_remove_sysfs_intf_files(struct usb_interface *intf) +void usb_remove_sysfs_intf_files (struct usb_interface *intf) { usb_remove_intf_ep_files(intf); sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); diff --git a/trunk/drivers/usb/core/urb.c b/trunk/drivers/usb/core/urb.c index 94ea9727ff55..9801d08edacf 100644 --- a/trunk/drivers/usb/core/urb.c +++ b/trunk/drivers/usb/core/urb.c @@ -235,15 +235,16 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) urb->status = -EINPROGRESS; urb->actual_length = 0; + urb->bandwidth = 0; /* Lots of sanity checks, so HCDs can rely on clean data * and don't need to duplicate tests */ pipe = urb->pipe; - temp = usb_pipetype(pipe); - is_out = usb_pipeout(pipe); + temp = usb_pipetype (pipe); + is_out = usb_pipeout (pipe); - if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED) + if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED) return -ENODEV; /* FIXME there should be a sharable lock protecting us against @@ -252,11 +253,11 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) * checks get made.) */ - max = usb_maxpacket(dev, pipe, is_out); + max = usb_maxpacket (dev, pipe, is_out); if (max <= 0) { dev_dbg(&dev->dev, "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n", - usb_pipeendpoint(pipe), is_out ? "out" : "in", + usb_pipeendpoint (pipe), is_out ? "out" : "in", __FUNCTION__, max); return -EMSGSIZE; } @@ -278,11 +279,11 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) if (urb->number_of_packets <= 0) return -EINVAL; for (n = 0; n < urb->number_of_packets; n++) { - len = urb->iso_frame_desc[n].length; + len = urb->iso_frame_desc [n].length; if (len < 0 || len > max) return -EMSGSIZE; - urb->iso_frame_desc[n].status = -EXDEV; - urb->iso_frame_desc[n].actual_length = 0; + urb->iso_frame_desc [n].status = -EXDEV; + urb->iso_frame_desc [n].actual_length = 0; } } @@ -321,7 +322,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) /* fail if submitter gave bogus flags */ if (urb->transfer_flags != orig_flags) { - err("BOGUS urb flags, %x --> %x", + err ("BOGUS urb flags, %x --> %x", orig_flags, urb->transfer_flags); return -EINVAL; } @@ -372,7 +373,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) urb->interval = temp; } - return usb_hcd_submit_urb(urb, mem_flags); + return usb_hcd_submit_urb (urb, mem_flags); } /*-------------------------------------------------------------------*/ diff --git a/trunk/drivers/usb/core/usb.c b/trunk/drivers/usb/core/usb.c index 3db721cd557a..02426d0b9a34 100644 --- a/trunk/drivers/usb/core/usb.c +++ b/trunk/drivers/usb/core/usb.c @@ -233,7 +233,7 @@ static void usb_autosuspend_work(struct work_struct *work) * @parent: hub to which device is connected; null to allocate a root hub * @bus: bus used to access the device * @port1: one-based index of port; ignored for root hubs - * Context: !in_interrupt() + * Context: !in_interrupt () * * Only hub drivers (including virtual root hub drivers for host * controllers) should ever call this. @@ -277,22 +277,22 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) * as stable: bus->busnum changes easily from modprobe order, * cardbus or pci hotplugging, and so on. */ - if (unlikely(!parent)) { - dev->devpath[0] = '0'; + if (unlikely (!parent)) { + dev->devpath [0] = '0'; dev->dev.parent = bus->controller; - sprintf(&dev->dev.bus_id[0], "usb%d", bus->busnum); + sprintf (&dev->dev.bus_id[0], "usb%d", bus->busnum); } else { /* match any labeling on the hubs; it's one-based */ - if (parent->devpath[0] == '0') - snprintf(dev->devpath, sizeof dev->devpath, + if (parent->devpath [0] == '0') + snprintf (dev->devpath, sizeof dev->devpath, "%d", port1); else - snprintf(dev->devpath, sizeof dev->devpath, + snprintf (dev->devpath, sizeof dev->devpath, "%s.%d", parent->devpath, port1); dev->dev.parent = &parent->dev; - sprintf(&dev->dev.bus_id[0], "%d-%s", + sprintf (&dev->dev.bus_id[0], "%d-%s", bus->busnum, dev->devpath); /* hub driver sets up TT records */ @@ -463,7 +463,7 @@ static struct usb_device *match_device(struct usb_device *dev, /* see if this device matches */ if ((vendor_id == le16_to_cpu(dev->descriptor.idVendor)) && (product_id == le16_to_cpu(dev->descriptor.idProduct))) { - dev_dbg(&dev->dev, "matched this device!\n"); + dev_dbg (&dev->dev, "matched this device!\n"); ret_dev = usb_get_dev(dev); goto exit; } @@ -535,7 +535,7 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) */ int usb_get_current_frame_number(struct usb_device *dev) { - return usb_hcd_get_frame_number(dev); + return usb_hcd_get_frame_number (dev); } /*-------------------------------------------------------------------*/ @@ -593,7 +593,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, * * When the buffer is no longer used, free it with usb_buffer_free(). */ -void *usb_buffer_alloc( +void *usb_buffer_alloc ( struct usb_device *dev, size_t size, gfp_t mem_flags, @@ -602,7 +602,7 @@ void *usb_buffer_alloc( { if (!dev || !dev->bus) return NULL; - return hcd_buffer_alloc(dev->bus, size, mem_flags, dma); + return hcd_buffer_alloc (dev->bus, size, mem_flags, dma); } /** @@ -616,7 +616,7 @@ void *usb_buffer_alloc( * been allocated using usb_buffer_alloc(), and the parameters must match * those provided in that allocation request. */ -void usb_buffer_free( +void usb_buffer_free ( struct usb_device *dev, size_t size, void *addr, @@ -627,7 +627,7 @@ void usb_buffer_free( return; if (!addr) return; - hcd_buffer_free(dev->bus, size, addr, dma); + hcd_buffer_free (dev->bus, size, addr, dma); } /** @@ -647,7 +647,7 @@ void usb_buffer_free( * Reverse the effect of this call with usb_buffer_unmap(). */ #if 0 -struct urb *usb_buffer_map(struct urb *urb) +struct urb *usb_buffer_map (struct urb *urb) { struct usb_bus *bus; struct device *controller; @@ -659,14 +659,14 @@ struct urb *usb_buffer_map(struct urb *urb) return NULL; if (controller->dma_mask) { - urb->transfer_dma = dma_map_single(controller, + urb->transfer_dma = dma_map_single (controller, urb->transfer_buffer, urb->transfer_buffer_length, - usb_pipein(urb->pipe) + usb_pipein (urb->pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); - if (usb_pipecontrol(urb->pipe)) - urb->setup_dma = dma_map_single(controller, + if (usb_pipecontrol (urb->pipe)) + urb->setup_dma = dma_map_single (controller, urb->setup_packet, - sizeof(struct usb_ctrlrequest), + sizeof (struct usb_ctrlrequest), DMA_TO_DEVICE); // FIXME generic api broken like pci, can't report errors // if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; @@ -689,7 +689,7 @@ struct urb *usb_buffer_map(struct urb *urb) * usb_buffer_dmasync - synchronize DMA and CPU view of buffer(s) * @urb: urb whose transfer_buffer/setup_packet will be synchronized */ -void usb_buffer_dmasync(struct urb *urb) +void usb_buffer_dmasync (struct urb *urb) { struct usb_bus *bus; struct device *controller; @@ -702,14 +702,14 @@ void usb_buffer_dmasync(struct urb *urb) return; if (controller->dma_mask) { - dma_sync_single(controller, + dma_sync_single (controller, urb->transfer_dma, urb->transfer_buffer_length, - usb_pipein(urb->pipe) + usb_pipein (urb->pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); - if (usb_pipecontrol(urb->pipe)) - dma_sync_single(controller, + if (usb_pipecontrol (urb->pipe)) + dma_sync_single (controller, urb->setup_dma, - sizeof(struct usb_ctrlrequest), + sizeof (struct usb_ctrlrequest), DMA_TO_DEVICE); } } @@ -722,7 +722,7 @@ void usb_buffer_dmasync(struct urb *urb) * Reverses the effect of usb_buffer_map(). */ #if 0 -void usb_buffer_unmap(struct urb *urb) +void usb_buffer_unmap (struct urb *urb) { struct usb_bus *bus; struct device *controller; @@ -735,14 +735,14 @@ void usb_buffer_unmap(struct urb *urb) return; if (controller->dma_mask) { - dma_unmap_single(controller, + dma_unmap_single (controller, urb->transfer_dma, urb->transfer_buffer_length, - usb_pipein(urb->pipe) + usb_pipein (urb->pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); - if (usb_pipecontrol(urb->pipe)) - dma_unmap_single(controller, + if (usb_pipecontrol (urb->pipe)) + dma_unmap_single (controller, urb->setup_dma, - sizeof(struct usb_ctrlrequest), + sizeof (struct usb_ctrlrequest), DMA_TO_DEVICE); } urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP @@ -783,15 +783,15 @@ int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe, struct device *controller; if (!dev - || usb_pipecontrol(pipe) + || usb_pipecontrol (pipe) || !(bus = dev->bus) || !(controller = bus->controller) || !controller->dma_mask) return -1; // FIXME generic api broken like pci, can't report errors - return dma_map_sg(controller, sg, nents, - usb_pipein(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + return dma_map_sg (controller, sg, nents, + usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } /* XXX DISABLED, no users currently. If you wish to re-enable this @@ -823,8 +823,8 @@ void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe, || !controller->dma_mask) return; - dma_sync_sg(controller, sg, n_hw_ents, - usb_pipein(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + dma_sync_sg (controller, sg, n_hw_ents, + usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } #endif @@ -849,8 +849,8 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe, || !controller->dma_mask) return; - dma_unmap_sg(controller, sg, n_hw_ents, - usb_pipein(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + dma_unmap_sg (controller, sg, n_hw_ents, + usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } /* format to disable USB on kernel command line is: nousb */ @@ -871,7 +871,7 @@ static int __init usb_init(void) { int retval; if (nousb) { - pr_info("%s: USB support disabled\n", usbcore_name); + pr_info ("%s: USB support disabled\n", usbcore_name); return 0; } @@ -971,19 +971,19 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor); EXPORT_SYMBOL(usb_find_device); EXPORT_SYMBOL(usb_get_current_frame_number); -EXPORT_SYMBOL(usb_buffer_alloc); -EXPORT_SYMBOL(usb_buffer_free); +EXPORT_SYMBOL (usb_buffer_alloc); +EXPORT_SYMBOL (usb_buffer_free); #if 0 -EXPORT_SYMBOL(usb_buffer_map); -EXPORT_SYMBOL(usb_buffer_dmasync); -EXPORT_SYMBOL(usb_buffer_unmap); +EXPORT_SYMBOL (usb_buffer_map); +EXPORT_SYMBOL (usb_buffer_dmasync); +EXPORT_SYMBOL (usb_buffer_unmap); #endif -EXPORT_SYMBOL(usb_buffer_map_sg); +EXPORT_SYMBOL (usb_buffer_map_sg); #if 0 -EXPORT_SYMBOL(usb_buffer_dmasync_sg); +EXPORT_SYMBOL (usb_buffer_dmasync_sg); #endif -EXPORT_SYMBOL(usb_buffer_unmap_sg); +EXPORT_SYMBOL (usb_buffer_unmap_sg); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/gadget/at91_udc.c b/trunk/drivers/usb/gadget/at91_udc.c index f39050145f1f..812c733ba8ce 100644 --- a/trunk/drivers/usb/gadget/at91_udc.c +++ b/trunk/drivers/usb/gadget/at91_udc.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include @@ -1807,13 +1807,16 @@ static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg) || !wake || at91_suspend_entering_slow_clock()) { pullup(udc, 0); - wake = 0; + disable_irq_wake(udc->udp_irq); } else enable_irq_wake(udc->udp_irq); - udc->active_suspend = wake; - if (udc->board.vbus_pin > 0 && wake) - enable_irq_wake(udc->board.vbus_pin); + if (udc->board.vbus_pin > 0) { + if (wake) + enable_irq_wake(udc->board.vbus_pin); + else + disable_irq_wake(udc->board.vbus_pin); + } return 0; } @@ -1821,14 +1824,8 @@ static int at91udc_resume(struct platform_device *pdev) { struct at91_udc *udc = platform_get_drvdata(pdev); - if (udc->board.vbus_pin > 0 && udc->active_suspend) - disable_irq_wake(udc->board.vbus_pin); - /* maybe reconnect to host; if so, clocks on */ - if (udc->active_suspend) - disable_irq_wake(udc->udp_irq); - else - pullup(udc, 1); + pullup(udc, 1); return 0; } #else diff --git a/trunk/drivers/usb/gadget/at91_udc.h b/trunk/drivers/usb/gadget/at91_udc.h index 7e34e2f864f9..677089baa59d 100644 --- a/trunk/drivers/usb/gadget/at91_udc.h +++ b/trunk/drivers/usb/gadget/at91_udc.h @@ -136,7 +136,6 @@ struct at91_udc { unsigned wait_for_addr_ack:1; unsigned wait_for_config_ack:1; unsigned selfpowered:1; - unsigned active_suspend:1; u8 addr; struct at91_udc_data board; struct clk *iclk, *fclk; diff --git a/trunk/drivers/usb/gadget/config.c b/trunk/drivers/usb/gadget/config.c index d18901b92cda..83b4866df9af 100644 --- a/trunk/drivers/usb/gadget/config.c +++ b/trunk/drivers/usb/gadget/config.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include diff --git a/trunk/drivers/usb/gadget/epautoconf.c b/trunk/drivers/usb/gadget/epautoconf.c index f28af06905a5..53d584589c26 100644 --- a/trunk/drivers/usb/gadget/epautoconf.c +++ b/trunk/drivers/usb/gadget/epautoconf.c @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include "gadget_chips.h" diff --git a/trunk/drivers/usb/gadget/ether.c b/trunk/drivers/usb/gadget/ether.c index 22e3c9443641..d15bf22b9a03 100644 --- a/trunk/drivers/usb/gadget/ether.c +++ b/trunk/drivers/usb/gadget/ether.c @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include @@ -72,18 +72,9 @@ * * There's some hardware that can't talk CDC. We make that hardware * implement a "minimalist" vendor-agnostic CDC core: same framing, but - * link-level setup only requires activating the configuration. Only the - * endpoint descriptors, and product/vendor IDs, are relevant; no control - * operations are available. Linux supports it, but other host operating - * systems may not. (This is a subset of CDC Ethernet.) - * - * It turns out that if you add a few descriptors to that "CDC Subset", - * (Windows) host side drivers from MCCI can treat it as one submode of - * a proprietary scheme called "SAFE" ... without needing to know about - * specific product/vendor IDs. So we do that, making it easier to use - * those MS-Windows drivers. Those added descriptors make it resemble a - * CDC MDLM device, but they don't change device behavior at all. (See - * MCCI Engineering report 950198 "SAFE Networking Functions".) + * link-level setup only requires activating the configuration. + * Linux supports it, but other host operating systems may not. + * (This is a subset of CDC Ethernet.) * * A third option is also in use. Rather than CDC Ethernet, or something * simpler, Microsoft pushes their own approach: RNDIS. The published @@ -263,10 +254,6 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_CDC #endif -#ifdef CONFIG_USB_GADGET_S3C2410 -#define DEV_CONFIG_CDC -#endif - #ifdef CONFIG_USB_GADGET_AT91 #define DEV_CONFIG_CDC #endif @@ -279,10 +266,6 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_CDC #endif -#ifdef CONFIG_USB_GADGET_HUSB2DEV -#define DEV_CONFIG_CDC -#endif - /* For CDC-incapable hardware, choose the simple cdc subset. * Anything that talks bulk (without notable bugs) can do this. @@ -300,6 +283,9 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_SUBSET #endif +#ifdef CONFIG_USB_GADGET_S3C2410 +#define DEV_CONFIG_CDC +#endif /*-------------------------------------------------------------------------*/ @@ -501,17 +487,8 @@ rndis_config = { * endpoint. Both have a "data" interface and two bulk endpoints. * There are also differences in how control requests are handled. * - * RNDIS shares a lot with CDC-Ethernet, since it's a variant of the - * CDC-ACM (modem) spec. Unfortunately MSFT's RNDIS driver is buggy; it - * may hang or oops. Since bugfixes (or accurate specs, letting Linux - * work around those bugs) are unlikely to ever come from MSFT, you may - * wish to avoid using RNDIS. - * - * MCCI offers an alternative to RNDIS if you need to connect to Windows - * but have hardware that can't support CDC Ethernet. We add descriptors - * to present the CDC Subset as a (nonconformant) CDC MDLM variant called - * "SAFE". That borrows from both CDC Ethernet and CDC MDLM. You can - * get those drivers from MCCI, or bundled with various products. + * RNDIS shares a lot with CDC-Ethernet, since it's a variant of + * the CDC-ACM (modem) spec. */ #ifdef DEV_CONFIG_CDC @@ -545,6 +522,8 @@ rndis_control_intf = { }; #endif +#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) + static const struct usb_cdc_header_desc header_desc = { .bLength = sizeof header_desc, .bDescriptorType = USB_DT_CS_INTERFACE, @@ -553,8 +532,6 @@ static const struct usb_cdc_header_desc header_desc = { .bcdCDC = __constant_cpu_to_le16 (0x0110), }; -#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - static const struct usb_cdc_union_desc union_desc = { .bLength = sizeof union_desc, .bDescriptorType = USB_DT_CS_INTERFACE, @@ -587,40 +564,7 @@ static const struct usb_cdc_acm_descriptor acm_descriptor = { #endif -#ifndef DEV_CONFIG_CDC - -/* "SAFE" loosely follows CDC WMC MDLM, violating the spec in various - * ways: data endpoints live in the control interface, there's no data - * interface, and it's not used to talk to a cell phone radio. - */ - -static const struct usb_cdc_mdlm_desc mdlm_desc = { - .bLength = sizeof mdlm_desc, - .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = USB_CDC_MDLM_TYPE, - - .bcdVersion = __constant_cpu_to_le16(0x0100), - .bGUID = { - 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, - 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, - }, -}; - -/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we - * can't really use its struct. All we do here is say that we're using - * the submode of "SAFE" which directly matches the CDC Subset. - */ -static const u8 mdlm_detail_desc[] = { - 6, - USB_DT_CS_INTERFACE, - USB_CDC_MDLM_DETAIL_TYPE, - - 0, /* "SAFE" */ - 0, /* network control capabilities (none) */ - 0, /* network data capabilities ("raw" encapsulation) */ -}; - -#endif +#ifdef DEV_CONFIG_CDC static const struct usb_cdc_ether_desc ether_desc = { .bLength = sizeof ether_desc, @@ -635,6 +579,7 @@ static const struct usb_cdc_ether_desc ether_desc = { .bNumberPowerFilters = 0, }; +#endif #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) @@ -727,9 +672,6 @@ rndis_data_intf = { /* * "Simple" CDC-subset option is a simple vendor-neutral model that most * full speed controllers can handle: one interface, two bulk endpoints. - * - * To assist host side drivers, we fancy it up a bit, and add descriptors - * so some host side drivers will understand it as a "SAFE" variant. */ static const struct usb_interface_descriptor @@ -740,8 +682,8 @@ subset_data_intf = { .bInterfaceNumber = 0, .bAlternateSetting = 0, .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 0, .bInterfaceProtocol = 0, .iInterface = STRING_DATA, }; @@ -789,15 +731,10 @@ static const struct usb_descriptor_header *fs_eth_function [11] = { static inline void __init fs_subset_descriptors(void) { #ifdef DEV_CONFIG_SUBSET - /* behavior is "CDC Subset"; extra descriptors say "SAFE" */ fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; - fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc; - fs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc; - fs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc; - fs_eth_function[5] = (struct usb_descriptor_header *) ðer_desc; - fs_eth_function[6] = (struct usb_descriptor_header *) &fs_source_desc; - fs_eth_function[7] = (struct usb_descriptor_header *) &fs_sink_desc; - fs_eth_function[8] = NULL; + fs_eth_function[2] = (struct usb_descriptor_header *) &fs_source_desc; + fs_eth_function[3] = (struct usb_descriptor_header *) &fs_sink_desc; + fs_eth_function[4] = NULL; #else fs_eth_function[1] = NULL; #endif @@ -891,15 +828,10 @@ static const struct usb_descriptor_header *hs_eth_function [11] = { static inline void __init hs_subset_descriptors(void) { #ifdef DEV_CONFIG_SUBSET - /* behavior is "CDC Subset"; extra descriptors say "SAFE" */ hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; - hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc; - hs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc; - hs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc; - hs_eth_function[5] = (struct usb_descriptor_header *) ðer_desc; - hs_eth_function[6] = (struct usb_descriptor_header *) &hs_source_desc; - hs_eth_function[7] = (struct usb_descriptor_header *) &hs_sink_desc; - hs_eth_function[8] = NULL; + hs_eth_function[2] = (struct usb_descriptor_header *) &fs_source_desc; + hs_eth_function[3] = (struct usb_descriptor_header *) &fs_sink_desc; + hs_eth_function[4] = NULL; #else hs_eth_function[1] = NULL; #endif @@ -946,8 +878,10 @@ static char manufacturer [50]; static char product_desc [40] = DRIVER_DESC; static char serial_number [20]; +#ifdef DEV_CONFIG_CDC /* address that the host will use ... usually assigned at random */ static char ethaddr [2 * ETH_ALEN + 1]; +#endif /* static strings, in UTF-8 */ static struct usb_string strings [] = { @@ -955,9 +889,9 @@ static struct usb_string strings [] = { { STRING_PRODUCT, product_desc, }, { STRING_SERIALNUMBER, serial_number, }, { STRING_DATA, "Ethernet Data", }, - { STRING_ETHADDR, ethaddr, }, #ifdef DEV_CONFIG_CDC { STRING_CDC, "CDC Ethernet", }, + { STRING_ETHADDR, ethaddr, }, { STRING_CONTROL, "CDC Communications Control", }, #endif #ifdef DEV_CONFIG_SUBSET @@ -1052,10 +986,10 @@ set_ether_config (struct eth_dev *dev, gfp_t gfp_flags) } #endif - dev->in = ep_desc(gadget, &hs_source_desc, &fs_source_desc); + dev->in = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); dev->in_ep->driver_data = dev; - dev->out = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc); + dev->out = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); dev->out_ep->driver_data = dev; /* With CDC, the host isn't allowed to use these two data @@ -2344,10 +2278,10 @@ eth_bind (struct usb_gadget *gadget) "RNDIS/%s", driver_desc); /* CDC subset ... recognized by Linux since 2.4.10, but Windows - * drivers aren't widely available. (That may be improved by - * supporting one submode of the "SAFE" variant of MDLM.) + * drivers aren't widely available. */ } else if (!cdc) { + device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; device_desc.idVendor = __constant_cpu_to_le16(SIMPLE_VENDOR_NUM); device_desc.idProduct = @@ -2418,10 +2352,6 @@ eth_bind (struct usb_gadget *gadget) if (!cdc) { eth_config.bNumInterfaces = 1; eth_config.iConfiguration = STRING_SUBSET; - - /* use functions to set these up, in case we're built to work - * with multiple controllers and must override CDC Ethernet. - */ fs_subset_descriptors(); hs_subset_descriptors(); } @@ -2485,20 +2415,22 @@ eth_bind (struct usb_gadget *gadget) /* Module params for these addresses should come from ID proms. * The host side address is used with CDC and RNDIS, and commonly - * ends up in a persistent config database. It's not clear if - * host side code for the SAFE thing cares -- its original BLAN - * thing didn't, Sharp never assigned those addresses on Zaurii. + * ends up in a persistent config database. */ if (get_ether_addr(dev_addr, net->dev_addr)) dev_warn(&gadget->dev, "using random %s ethernet address\n", "self"); - if (get_ether_addr(host_addr, dev->host_mac)) - dev_warn(&gadget->dev, - "using random %s ethernet address\n", "host"); - snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", - dev->host_mac [0], dev->host_mac [1], - dev->host_mac [2], dev->host_mac [3], - dev->host_mac [4], dev->host_mac [5]); + if (cdc || rndis) { + if (get_ether_addr(host_addr, dev->host_mac)) + dev_warn(&gadget->dev, + "using random %s ethernet address\n", "host"); +#ifdef DEV_CONFIG_CDC + snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", + dev->host_mac [0], dev->host_mac [1], + dev->host_mac [2], dev->host_mac [3], + dev->host_mac [4], dev->host_mac [5]); +#endif + } if (rndis) { status = rndis_init(); diff --git a/trunk/drivers/usb/gadget/file_storage.c b/trunk/drivers/usb/gadget/file_storage.c index f04a29a46646..72f2ae96fbf3 100644 --- a/trunk/drivers/usb/gadget/file_storage.c +++ b/trunk/drivers/usb/gadget/file_storage.c @@ -253,7 +253,7 @@ #include #include -#include +#include #include #include "gadget_chips.h" @@ -1148,7 +1148,7 @@ static int ep0_queue(struct fsg_dev *fsg) static void ep0_complete(struct usb_ep *ep, struct usb_request *req) { - struct fsg_dev *fsg = ep->driver_data; + struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; if (req->actual > 0) dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual); @@ -1170,8 +1170,8 @@ static void ep0_complete(struct usb_ep *ep, struct usb_request *req) static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) { - struct fsg_dev *fsg = ep->driver_data; - struct fsg_buffhd *bh = req->context; + struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; + struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; if (req->status || req->actual != req->length) DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__, @@ -1190,8 +1190,8 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) { - struct fsg_dev *fsg = ep->driver_data; - struct fsg_buffhd *bh = req->context; + struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; + struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; dump_msg(fsg, "bulk-out", req->buf, req->actual); if (req->status || req->actual != bh->bulk_out_intended_length) @@ -1214,8 +1214,8 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) #ifdef CONFIG_USB_FILE_STORAGE_TEST static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) { - struct fsg_dev *fsg = ep->driver_data; - struct fsg_buffhd *bh = req->context; + struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; + struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; if (req->status || req->actual != req->length) DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__, @@ -2577,7 +2577,7 @@ static int send_status(struct fsg_dev *fsg) } if (transport_is_bbb()) { - struct bulk_cs_wrap *csw = bh->buf; + struct bulk_cs_wrap *csw = (struct bulk_cs_wrap *) bh->buf; /* Store and send the Bulk-only CSW */ csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG); @@ -2596,7 +2596,8 @@ static int send_status(struct fsg_dev *fsg) return 0; } else { // USB_PR_CBI - struct interrupt_data *buf = bh->buf; + struct interrupt_data *buf = (struct interrupt_data *) + bh->buf; /* Store and send the Interrupt data. UFI sends the ASC * and ASCQ bytes. Everything else sends a Type (which @@ -2981,7 +2982,7 @@ static int do_scsi_command(struct fsg_dev *fsg) static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) { struct usb_request *req = bh->outreq; - struct bulk_cb_wrap *cbw = req->buf; + struct bulk_cb_wrap *cbw = (struct bulk_cb_wrap *) req->buf; /* Was this a real packet? */ if (req->status) @@ -3427,7 +3428,7 @@ static void handle_exception(struct fsg_dev *fsg) static int fsg_main_thread(void *fsg_) { - struct fsg_dev *fsg = fsg_; + struct fsg_dev *fsg = (struct fsg_dev *) fsg_; /* Allow the thread to be killed by a signal, but set the signal mask * to block everything but INT, TERM, KILL, and USR1. */ @@ -3599,7 +3600,7 @@ static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char * static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf) { struct lun *curlun = dev_to_lun(dev); - struct fsg_dev *fsg = dev_get_drvdata(dev); + struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); char *p; ssize_t rc; @@ -3628,7 +3629,7 @@ static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const { ssize_t rc = count; struct lun *curlun = dev_to_lun(dev); - struct fsg_dev *fsg = dev_get_drvdata(dev); + struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); int i; if (sscanf(buf, "%d", &i) != 1) @@ -3651,7 +3652,7 @@ static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct lun *curlun = dev_to_lun(dev); - struct fsg_dev *fsg = dev_get_drvdata(dev); + struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); int rc = 0; if (curlun->prevent_medium_removal && backing_file_is_open(curlun)) { @@ -3699,7 +3700,7 @@ static void fsg_release(struct kref *ref) static void lun_release(struct device *dev) { - struct fsg_dev *fsg = dev_get_drvdata(dev); + struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); kref_put(&fsg->ref, fsg_release); } diff --git a/trunk/drivers/usb/gadget/gadget_chips.h b/trunk/drivers/usb/gadget/gadget_chips.h index 2e3d6620d216..aa80f0910720 100644 --- a/trunk/drivers/usb/gadget/gadget_chips.h +++ b/trunk/drivers/usb/gadget/gadget_chips.h @@ -75,12 +75,6 @@ #define gadget_is_pxa27x(g) 0 #endif -#ifdef CONFIG_USB_GADGET_HUSB2DEV -#define gadget_is_husb2dev(g) !strcmp("husb2_udc", (g)->name) -#else -#define gadget_is_husb2dev(g) 0 -#endif - #ifdef CONFIG_USB_GADGET_S3C2410 #define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name) #else @@ -175,7 +169,5 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x16; else if (gadget_is_mpc8272(gadget)) return 0x17; - else if (gadget_is_husb2dev(gadget)) - return 0x18; return -ENOENT; } diff --git a/trunk/drivers/usb/gadget/gmidi.c b/trunk/drivers/usb/gadget/gmidi.c index d08a8d0e6427..f1a679656c96 100644 --- a/trunk/drivers/usb/gadget/gmidi.c +++ b/trunk/drivers/usb/gadget/gmidi.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include #include diff --git a/trunk/drivers/usb/gadget/goku_udc.c b/trunk/drivers/usb/gadget/goku_udc.c index e873cf488246..d0ef1d6b3fac 100644 --- a/trunk/drivers/usb/gadget/goku_udc.c +++ b/trunk/drivers/usb/gadget/goku_udc.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include diff --git a/trunk/drivers/usb/gadget/inode.c b/trunk/drivers/usb/gadget/inode.c index 34296e79edcf..3fb1044a4db0 100644 --- a/trunk/drivers/usb/gadget/inode.c +++ b/trunk/drivers/usb/gadget/inode.c @@ -20,7 +20,7 @@ */ -// #define DEBUG /* data to help fault diagnosis */ +// #define DEBUG /* data to help fault diagnosis */ // #define VERBOSE /* extra debug messages (success too) */ #include @@ -59,11 +59,11 @@ * may serve as a source of device events, used to handle all control * requests other than basic enumeration. * - * - Then, after a SET_CONFIGURATION control request, ep_config() is - * called when each /dev/gadget/ep* file is configured (by writing - * endpoint descriptors). Afterwards these files are used to write() - * IN data or to read() OUT data. To halt the endpoint, a "wrong - * direction" request is issued (like reading an IN endpoint). + * - Then either immediately, or after a SET_CONFIGURATION control request, + * ep_config() is called when each /dev/gadget/ep* file is configured + * (by writing endpoint descriptors). Afterwards these files are used + * to write() IN data or to read() OUT data. To halt the endpoint, a + * "wrong direction" request is issued (like reading an IN endpoint). * * Unlike "usbfs" the only ioctl()s are for things that are rare, and maybe * not possible on all hardware. For example, precise fault handling with @@ -98,16 +98,16 @@ enum ep0_state { * must always write descriptors to initialize the device, then * the device becomes UNCONNECTED until enumeration. */ - STATE_DEV_OPENED, + STATE_OPENED, /* From then on, ep0 fd is in either of two basic modes: * - (UN)CONNECTED: read usb_gadgetfs_event(s) from it * - SETUP: read/write will transfer control data and succeed; * or if "wrong direction", performs protocol stall */ - STATE_DEV_UNCONNECTED, - STATE_DEV_CONNECTED, - STATE_DEV_SETUP, + STATE_UNCONNECTED, + STATE_CONNECTED, + STATE_SETUP, /* UNBOUND means the driver closed ep0, so the device won't be * accessible again (DEV_DISABLED) until all fds are closed. @@ -121,7 +121,7 @@ enum ep0_state { struct dev_data { spinlock_t lock; atomic_t count; - enum ep0_state state; /* P: lock */ + enum ep0_state state; struct usb_gadgetfs_event event [N_EVENT]; unsigned ev_next; struct fasync_struct *fasync; @@ -188,6 +188,7 @@ static struct dev_data *dev_new (void) enum ep_state { STATE_EP_DISABLED = 0, STATE_EP_READY, + STATE_EP_DEFER_ENABLE, STATE_EP_ENABLED, STATE_EP_UNBOUND, }; @@ -312,10 +313,18 @@ get_ready_ep (unsigned f_flags, struct ep_data *epdata) if ((val = down_interruptible (&epdata->lock)) < 0) return val; - +newstate: switch (epdata->state) { case STATE_EP_ENABLED: break; + case STATE_EP_DEFER_ENABLE: + DBG (epdata->dev, "%s wait for host\n", epdata->name); + if ((val = wait_event_interruptible (epdata->wait, + epdata->state != STATE_EP_DEFER_ENABLE + || epdata->dev->state == STATE_DEV_UNBOUND + )) < 0) + goto fail; + goto newstate; // case STATE_EP_DISABLED: /* "can't happen" */ // case STATE_EP_READY: /* "can't happen" */ default: /* error! */ @@ -324,6 +333,7 @@ get_ready_ep (unsigned f_flags, struct ep_data *epdata) // FALLTHROUGH case STATE_EP_UNBOUND: /* clean disconnect */ val = -ENODEV; +fail: up (&epdata->lock); } return val; @@ -555,28 +565,29 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) ssize_t len, total; int i; - /* we "retry" to get the right mm context for this: */ - - /* copy stuff into user buffers */ - total = priv->actual; - len = 0; - for (i=0; i < priv->nr_segs; i++) { - ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total); - - if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) { - if (len == 0) - len = -EFAULT; - break; - } - - total -= this; - len += this; - if (total == 0) - break; - } - kfree(priv->buf); - kfree(priv); - return len; + /* we "retry" to get the right mm context for this: */ + + /* copy stuff into user buffers */ + total = priv->actual; + len = 0; + for (i=0; i < priv->nr_segs; i++) { + ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total); + + if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) { + if (len == 0) + len = -EFAULT; + break; + } + + total -= this; + len += this; + if (total == 0) + break; + } + kfree(priv->buf); + kfree(priv); + aio_put_req(iocb); + return len; } static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) @@ -589,17 +600,18 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) spin_lock(&epdata->dev->lock); priv->req = NULL; priv->epdata = NULL; - - /* if this was a write or a read returning no data then we - * don't need to copy anything to userspace, so we can - * complete the aio request immediately. - */ - if (priv->iv == NULL || unlikely(req->actual == 0)) { + if (priv->iv == NULL + || unlikely(req->actual == 0) + || unlikely(kiocbIsCancelled(iocb))) { kfree(req->buf); kfree(priv); iocb->private = NULL; /* aio_complete() reports bytes-transferred _and_ faults */ - aio_complete(iocb, req->actual ? req->actual : req->status, + if (unlikely(kiocbIsCancelled(iocb))) + aio_put_req(iocb); + else + aio_complete(iocb, + req->actual ? req->actual : req->status, req->status); } else { /* retry() won't report both; so we hide some faults */ @@ -624,7 +636,7 @@ ep_aio_rwtail( size_t len, struct ep_data *epdata, const struct iovec *iv, - unsigned long nr_segs + unsigned long nr_segs ) { struct kiocb_priv *priv; @@ -840,9 +852,9 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) break; #endif default: - DBG(data->dev, "unconnected, %s init abandoned\n", + DBG (data->dev, "unconnected, %s init deferred\n", data->name); - value = -EINVAL; + data->state = STATE_EP_DEFER_ENABLE; } if (value == 0) { fd->f_op = &ep_io_operations; @@ -931,24 +943,22 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req) static void ep0_complete (struct usb_ep *ep, struct usb_request *req) { struct dev_data *dev = ep->driver_data; - unsigned long flags; int free = 1; /* for control OUT, data must still get to userspace */ - spin_lock_irqsave(&dev->lock, flags); if (!dev->setup_in) { dev->setup_out_error = (req->status != 0); if (!dev->setup_out_error) free = 0; dev->setup_out_ready = 1; ep0_readable (dev); - } + } else if (dev->state == STATE_SETUP) + dev->state = STATE_CONNECTED; /* clean up as appropriate */ if (free && req->buf != &dev->rbuf) clean_req (ep, req); req->complete = epio_complete; - spin_unlock_irqrestore(&dev->lock, flags); } static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len) @@ -988,13 +998,13 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) } /* control DATA stage */ - if ((state = dev->state) == STATE_DEV_SETUP) { + if ((state = dev->state) == STATE_SETUP) { if (dev->setup_in) { /* stall IN */ VDEBUG(dev, "ep0in stall\n"); (void) usb_ep_set_halt (dev->gadget->ep0); retval = -EL2HLT; - dev->state = STATE_DEV_CONNECTED; + dev->state = STATE_CONNECTED; } else if (len == 0) { /* ack SET_CONFIGURATION etc */ struct usb_ep *ep = dev->gadget->ep0; @@ -1002,7 +1012,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) if ((retval = setup_req (ep, req, 0)) == 0) retval = usb_ep_queue (ep, req, GFP_ATOMIC); - dev->state = STATE_DEV_CONNECTED; + dev->state = STATE_CONNECTED; /* assume that was SET_CONFIGURATION */ if (dev->current_config) { @@ -1030,13 +1040,6 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) spin_lock_irq (&dev->lock); if (retval) goto done; - - if (dev->state != STATE_DEV_SETUP) { - retval = -ECANCELED; - goto done; - } - dev->state = STATE_DEV_CONNECTED; - if (dev->setup_out_error) retval = -EIO; else { @@ -1063,36 +1066,39 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) /* return queued events right away */ if (dev->ev_next != 0) { unsigned i, n; + int tmp = dev->ev_next; + len = min (len, tmp * sizeof (struct usb_gadgetfs_event)); n = len / sizeof (struct usb_gadgetfs_event); - if (dev->ev_next < n) - n = dev->ev_next; - /* ep0 i/o has special semantics during STATE_DEV_SETUP */ + /* ep0 can't deliver events when STATE_SETUP */ for (i = 0; i < n; i++) { if (dev->event [i].type == GADGETFS_SETUP) { - dev->state = STATE_DEV_SETUP; - n = i + 1; + len = i + 1; + len *= sizeof (struct usb_gadgetfs_event); + n = 0; break; } } spin_unlock_irq (&dev->lock); - len = n * sizeof (struct usb_gadgetfs_event); if (copy_to_user (buf, &dev->event, len)) retval = -EFAULT; else retval = len; if (len > 0) { + len /= sizeof (struct usb_gadgetfs_event); + /* NOTE this doesn't guard against broken drivers; * concurrent ep0 readers may lose events. */ spin_lock_irq (&dev->lock); - if (dev->ev_next > n) { - memmove(&dev->event[0], &dev->event[n], + dev->ev_next -= len; + if (dev->ev_next != 0) + memmove (&dev->event, &dev->event [len], sizeof (struct usb_gadgetfs_event) - * (dev->ev_next - n)); - } - dev->ev_next -= n; + * (tmp - len)); + if (n == 0) + dev->state = STATE_SETUP; spin_unlock_irq (&dev->lock); } return retval; @@ -1107,8 +1113,8 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) DBG (dev, "fail %s, state %d\n", __FUNCTION__, state); retval = -ESRCH; break; - case STATE_DEV_UNCONNECTED: - case STATE_DEV_CONNECTED: + case STATE_UNCONNECTED: + case STATE_CONNECTED: spin_unlock_irq (&dev->lock); DBG (dev, "%s wait\n", __FUNCTION__); @@ -1135,7 +1141,7 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type) switch (type) { /* these events purge the queue */ case GADGETFS_DISCONNECT: - if (dev->state == STATE_DEV_SETUP) + if (dev->state == STATE_SETUP) dev->setup_abort = 1; // FALL THROUGH case GADGETFS_CONNECT: @@ -1147,7 +1153,7 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type) for (i = 0; i != dev->ev_next; i++) { if (dev->event [i].type != type) continue; - DBG(dev, "discard old event[%d] %d\n", i, type); + DBG (dev, "discard old event %d\n", type); dev->ev_next--; if (i == dev->ev_next) break; @@ -1160,9 +1166,9 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type) default: BUG (); } - VDEBUG(dev, "event[%d] = %d\n", dev->ev_next, type); event = &dev->event [dev->ev_next++]; BUG_ON (dev->ev_next > N_EVENT); + VDEBUG (dev, "ev %d, next %d\n", type, dev->ev_next); memset (event, 0, sizeof *event); event->type = type; return event; @@ -1182,13 +1188,12 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) retval = -EIDRM; /* data and/or status stage for control request */ - } else if (dev->state == STATE_DEV_SETUP) { + } else if (dev->state == STATE_SETUP) { /* IN DATA+STATUS caller makes len <= wLength */ if (dev->setup_in) { retval = setup_req (dev->gadget->ep0, dev->req, len); if (retval == 0) { - dev->state = STATE_DEV_CONNECTED; spin_unlock_irq (&dev->lock); if (copy_from_user (dev->req->buf, buf, len)) retval = -EFAULT; @@ -1214,7 +1219,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) VDEBUG(dev, "ep0out stall\n"); (void) usb_ep_set_halt (dev->gadget->ep0); retval = -EL2HLT; - dev->state = STATE_DEV_CONNECTED; + dev->state = STATE_CONNECTED; } else { DBG(dev, "bogus ep0out stall!\n"); } @@ -1256,9 +1261,7 @@ dev_release (struct inode *inode, struct file *fd) put_dev (dev); /* other endpoints were all decoupled from this device */ - spin_lock_irq(&dev->lock); dev->state = STATE_DEV_DISABLED; - spin_unlock_irq(&dev->lock); return 0; } @@ -1279,7 +1282,7 @@ ep0_poll (struct file *fd, poll_table *wait) goto out; } - if (dev->state == STATE_DEV_SETUP) { + if (dev->state == STATE_SETUP) { if (dev->setup_in || dev->setup_can_stall) mask = POLLOUT; } else { @@ -1389,29 +1392,52 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) spin_lock (&dev->lock); dev->setup_abort = 0; - if (dev->state == STATE_DEV_UNCONNECTED) { + if (dev->state == STATE_UNCONNECTED) { + struct usb_ep *ep; + struct ep_data *data; + + dev->state = STATE_CONNECTED; + dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket; + #ifdef CONFIG_USB_GADGET_DUALSPEED if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) { - spin_unlock(&dev->lock); ERROR (dev, "no high speed config??\n"); return -EINVAL; } #endif /* CONFIG_USB_GADGET_DUALSPEED */ - dev->state = STATE_DEV_CONNECTED; - dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket; - INFO (dev, "connected\n"); event = next_event (dev, GADGETFS_CONNECT); event->u.speed = gadget->speed; ep0_readable (dev); + list_for_each_entry (ep, &gadget->ep_list, ep_list) { + data = ep->driver_data; + /* ... down_trylock (&data->lock) ... */ + if (data->state != STATE_EP_DEFER_ENABLE) + continue; +#ifdef CONFIG_USB_GADGET_DUALSPEED + if (gadget->speed == USB_SPEED_HIGH) + value = usb_ep_enable (ep, &data->hs_desc); + else +#endif /* CONFIG_USB_GADGET_DUALSPEED */ + value = usb_ep_enable (ep, &data->desc); + if (value) { + ERROR (dev, "deferred %s enable --> %d\n", + data->name, value); + continue; + } + data->state = STATE_EP_ENABLED; + wake_up (&data->wait); + DBG (dev, "woke up %s waiters\n", data->name); + } + /* host may have given up waiting for response. we can miss control * requests handled lower down (device/endpoint status and features); * then ep0_{read,write} will report the wrong status. controller * driver will have aborted pending i/o. */ - } else if (dev->state == STATE_DEV_SETUP) + } else if (dev->state == STATE_SETUP) dev->setup_abort = 1; req->buf = dev->rbuf; @@ -1557,7 +1583,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) } /* proceed with data transfer and status phases? */ - if (value >= 0 && dev->state != STATE_DEV_SETUP) { + if (value >= 0 && dev->state != STATE_SETUP) { req->length = value; req->zero = value < w_length; value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); @@ -1721,9 +1747,7 @@ gadgetfs_bind (struct usb_gadget *gadget) goto enomem; INFO (dev, "bound to %s driver\n", gadget->name); - spin_lock_irq(&dev->lock); - dev->state = STATE_DEV_UNCONNECTED; - spin_unlock_irq(&dev->lock); + dev->state = STATE_UNCONNECTED; get_dev (dev); return 0; @@ -1738,9 +1762,11 @@ gadgetfs_disconnect (struct usb_gadget *gadget) struct dev_data *dev = get_gadget_data (gadget); spin_lock (&dev->lock); - if (dev->state == STATE_DEV_UNCONNECTED) + if (dev->state == STATE_UNCONNECTED) { + DBG (dev, "already unconnected\n"); goto exit; - dev->state = STATE_DEV_UNCONNECTED; + } + dev->state = STATE_UNCONNECTED; INFO (dev, "disconnected\n"); next_event (dev, GADGETFS_DISCONNECT); @@ -1757,9 +1783,9 @@ gadgetfs_suspend (struct usb_gadget *gadget) INFO (dev, "suspended from state %d\n", dev->state); spin_lock (&dev->lock); switch (dev->state) { - case STATE_DEV_SETUP: // VERY odd... host died?? - case STATE_DEV_CONNECTED: - case STATE_DEV_UNCONNECTED: + case STATE_SETUP: // VERY odd... host died?? + case STATE_CONNECTED: + case STATE_UNCONNECTED: next_event (dev, GADGETFS_SUSPEND); ep0_readable (dev); /* FALLTHROUGH */ @@ -1782,7 +1808,7 @@ static struct usb_gadget_driver gadgetfs_driver = { .disconnect = gadgetfs_disconnect, .suspend = gadgetfs_suspend, - .driver = { + .driver = { .name = (char *) shortname, }, }; @@ -1803,7 +1829,7 @@ static struct usb_gadget_driver probe_driver = { .unbind = gadgetfs_nop, .setup = (void *)gadgetfs_nop, .disconnect = gadgetfs_nop, - .driver = { + .driver = { .name = "nop", }, }; @@ -1823,16 +1849,19 @@ static struct usb_gadget_driver probe_driver = { * . full/low speed config ... all wTotalLength bytes (with interface, * class, altsetting, endpoint, and other descriptors) * . high speed config ... all descriptors, for high speed operation; - * this one's optional except for high-speed hardware + * this one's optional except for high-speed hardware * . device descriptor * - * Endpoints are not yet enabled. Drivers must wait until device - * configuration and interface altsetting changes create + * Endpoints are not yet enabled. Drivers may want to immediately + * initialize them, using the /dev/gadget/ep* files that are available + * as soon as the kernel sees the configuration, or they can wait + * until device configuration and interface altsetting changes create * the need to configure (or unconfigure) them. * * After initialization, the device stays active for as long as that - * $CHIP file is open. Events must then be read from that descriptor, - * such as configuration notifications. + * $CHIP file is open. Events may then be read from that descriptor, + * such as configuration notifications. More complex drivers will handle + * some control requests in user space. */ static int is_valid_config (struct usb_config_descriptor *config) @@ -1855,6 +1884,9 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) u32 tag; char *kbuf; + if (dev->state != STATE_OPENED) + return -EEXIST; + if (len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4)) return -EINVAL; @@ -1946,15 +1978,13 @@ dev_open (struct inode *inode, struct file *fd) struct dev_data *dev = inode->i_private; int value = -EBUSY; - spin_lock_irq(&dev->lock); if (dev->state == STATE_DEV_DISABLED) { dev->ev_next = 0; - dev->state = STATE_DEV_OPENED; + dev->state = STATE_OPENED; fd->private_data = dev; get_dev (dev); value = 0; } - spin_unlock_irq(&dev->lock); return value; } diff --git a/trunk/drivers/usb/gadget/lh7a40x_udc.h b/trunk/drivers/usb/gadget/lh7a40x_udc.h index b3fe197e1eeb..e3bb78524c88 100644 --- a/trunk/drivers/usb/gadget/lh7a40x_udc.h +++ b/trunk/drivers/usb/gadget/lh7a40x_udc.h @@ -49,7 +49,7 @@ #include #include -#include +#include #include /* diff --git a/trunk/drivers/usb/gadget/net2280.c b/trunk/drivers/usb/gadget/net2280.c index 7617ff7bd5ac..569eb8ccf232 100644 --- a/trunk/drivers/usb/gadget/net2280.c +++ b/trunk/drivers/usb/gadget/net2280.c @@ -63,7 +63,7 @@ #include #include #include -#include +#include #include #include diff --git a/trunk/drivers/usb/gadget/omap_udc.c b/trunk/drivers/usb/gadget/omap_udc.c index 140104341db4..cdcfd42843d4 100644 --- a/trunk/drivers/usb/gadget/omap_udc.c +++ b/trunk/drivers/usb/gadget/omap_udc.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/drivers/usb/gadget/pxa2xx_udc.c b/trunk/drivers/usb/gadget/pxa2xx_udc.c index 0d225369847d..b78de9694665 100644 --- a/trunk/drivers/usb/gadget/pxa2xx_udc.c +++ b/trunk/drivers/usb/gadget/pxa2xx_udc.c @@ -56,7 +56,7 @@ #include #endif -#include +#include #include #include diff --git a/trunk/drivers/usb/gadget/serial.c b/trunk/drivers/usb/gadget/serial.c index 6c742a909225..f8a3ec64635d 100644 --- a/trunk/drivers/usb/gadget/serial.c +++ b/trunk/drivers/usb/gadget/serial.c @@ -43,7 +43,7 @@ #include #include -#include +#include #include #include diff --git a/trunk/drivers/usb/gadget/usbstring.c b/trunk/drivers/usb/gadget/usbstring.c index 3459ea6c6c0b..b1735767660b 100644 --- a/trunk/drivers/usb/gadget/usbstring.c +++ b/trunk/drivers/usb/gadget/usbstring.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/trunk/drivers/usb/gadget/zero.c b/trunk/drivers/usb/gadget/zero.c index ebe04e0d2879..40710ea1b490 100644 --- a/trunk/drivers/usb/gadget/zero.c +++ b/trunk/drivers/usb/gadget/zero.c @@ -84,7 +84,7 @@ #include #include -#include +#include #include #include "gadget_chips.h" diff --git a/trunk/drivers/usb/host/Kconfig b/trunk/drivers/usb/host/Kconfig index 62711870f8ee..cc60759083bf 100644 --- a/trunk/drivers/usb/host/Kconfig +++ b/trunk/drivers/usb/host/Kconfig @@ -67,11 +67,6 @@ config USB_EHCI_TT_NEWSCHED If unsure, say N. -config USB_EHCI_BIG_ENDIAN_MMIO - bool - depends on USB_EHCI_HCD - default n - config USB_ISP116X_HCD tristate "ISP116X HCD support" depends on USB @@ -106,48 +101,21 @@ config USB_OHCI_HCD_PPC_SOC bool "OHCI support for on-chip PPC USB controller" depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) default y - select USB_OHCI_BIG_ENDIAN_DESC - select USB_OHCI_BIG_ENDIAN_MMIO + select USB_OHCI_BIG_ENDIAN ---help--- Enables support for the USB controller on the MPC52xx or STB03xxx processor chip. If unsure, say Y. -config USB_OHCI_HCD_PPC_OF - bool "OHCI support for PPC USB controller on OF platform bus" - depends on USB_OHCI_HCD && PPC_OF - default y - ---help--- - Enables support for the USB controller PowerPC present on the - OpenFirmware platform bus. - -config USB_OHCI_HCD_PPC_OF_BE - bool "Support big endian HC" - depends on USB_OHCI_HCD_PPC_OF - default y - select USB_OHCI_BIG_ENDIAN_DESC - select USB_OHCI_BIG_ENDIAN_MMIO - -config USB_OHCI_HCD_PPC_OF_LE - bool "Support little endian HC" - depends on USB_OHCI_HCD_PPC_OF - default n - select USB_OHCI_LITTLE_ENDIAN - config USB_OHCI_HCD_PCI bool "OHCI support for PCI-bus USB controllers" - depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF) + depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx) default y select USB_OHCI_LITTLE_ENDIAN ---help--- Enables support for PCI-bus plug-in USB controller cards. If unsure, say Y. -config USB_OHCI_BIG_ENDIAN_DESC - bool - depends on USB_OHCI_HCD - default n - -config USB_OHCI_BIG_ENDIAN_MMIO +config USB_OHCI_BIG_ENDIAN bool depends on USB_OHCI_HCD default n diff --git a/trunk/drivers/usb/host/ehci-dbg.c b/trunk/drivers/usb/host/ehci-dbg.c index 246afea9e83b..56349d21e6ea 100644 --- a/trunk/drivers/usb/host/ehci-dbg.c +++ b/trunk/drivers/usb/host/ehci-dbg.c @@ -43,7 +43,7 @@ */ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) { - u32 params = ehci_readl(ehci, &ehci->caps->hcs_params); + u32 params = readl (&ehci->caps->hcs_params); ehci_dbg (ehci, "%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n", @@ -87,7 +87,7 @@ static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} * */ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) { - u32 params = ehci_readl(ehci, &ehci->caps->hcc_params); + u32 params = readl (&ehci->caps->hcc_params); if (HCC_ISOC_CACHE (params)) { ehci_dbg (ehci, @@ -653,7 +653,7 @@ show_registers (struct class_device *class_dev, char *buf) } /* Capability Registers */ - i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); + i = HC_VERSION(readl (&ehci->caps->hc_capbase)); temp = scnprintf (next, size, "bus %s, device %s (driver " DRIVER_VERSION ")\n" "%s\n" @@ -673,7 +673,7 @@ show_registers (struct class_device *class_dev, char *buf) unsigned count = 256/4; pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); - offset = HCC_EXT_CAPS (ehci_readl(ehci, &ehci->caps->hcc_params)); + offset = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); while (offset && count--) { pci_read_config_dword (pdev, offset, &cap); switch (cap & 0xff) { @@ -704,50 +704,50 @@ show_registers (struct class_device *class_dev, char *buf) #endif // FIXME interpret both types of params - i = ehci_readl(ehci, &ehci->caps->hcs_params); + i = readl (&ehci->caps->hcs_params); temp = scnprintf (next, size, "structural params 0x%08x\n", i); size -= temp; next += temp; - i = ehci_readl(ehci, &ehci->caps->hcc_params); + i = readl (&ehci->caps->hcc_params); temp = scnprintf (next, size, "capability params 0x%08x\n", i); size -= temp; next += temp; /* Operational Registers */ temp = dbg_status_buf (scratch, sizeof scratch, label, - ehci_readl(ehci, &ehci->regs->status)); + readl (&ehci->regs->status)); temp = scnprintf (next, size, fmt, temp, scratch); size -= temp; next += temp; temp = dbg_command_buf (scratch, sizeof scratch, label, - ehci_readl(ehci, &ehci->regs->command)); + readl (&ehci->regs->command)); temp = scnprintf (next, size, fmt, temp, scratch); size -= temp; next += temp; temp = dbg_intr_buf (scratch, sizeof scratch, label, - ehci_readl(ehci, &ehci->regs->intr_enable)); + readl (&ehci->regs->intr_enable)); temp = scnprintf (next, size, fmt, temp, scratch); size -= temp; next += temp; temp = scnprintf (next, size, "uframe %04x\n", - ehci_readl(ehci, &ehci->regs->frame_index)); + readl (&ehci->regs->frame_index)); size -= temp; next += temp; for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { temp = dbg_port_buf (scratch, sizeof scratch, label, i, - ehci_readl(ehci, &ehci->regs->port_status [i - 1])); + readl (&ehci->regs->port_status [i - 1])); temp = scnprintf (next, size, fmt, temp, scratch); size -= temp; next += temp; if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { temp = scnprintf (next, size, " debug control %08x\n", - ehci_readl(ehci, &ehci->debug->control)); + readl (&ehci->debug->control)); size -= temp; next += temp; } diff --git a/trunk/drivers/usb/host/ehci-fsl.c b/trunk/drivers/usb/host/ehci-fsl.c index a52480505f78..1a915e982c1c 100644 --- a/trunk/drivers/usb/host/ehci-fsl.c +++ b/trunk/drivers/usb/host/ehci-fsl.c @@ -177,7 +177,7 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci, case FSL_USB2_PHY_NONE: break; } - ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); + writel(portsc, &ehci->regs->port_status[port_offset]); } static void mpc83xx_usb_setup(struct usb_hcd *hcd) @@ -214,7 +214,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) } /* put controller in host mode. */ - ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE); + writel(0x00000003, non_ehci + FSL_SOC_USB_USBMODE); out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); @@ -238,12 +238,12 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; ehci->regs = hcd->regs + 0x100 + - HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); + HC_LENGTH(readl(&ehci->caps->hc_capbase)); dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); + ehci->hcs_params = readl(&ehci->caps->hcs_params); retval = ehci_halt(ehci); if (retval) diff --git a/trunk/drivers/usb/host/ehci-hcd.c b/trunk/drivers/usb/host/ehci-hcd.c index 185721dba42b..025d33313681 100644 --- a/trunk/drivers/usb/host/ehci-hcd.c +++ b/trunk/drivers/usb/host/ehci-hcd.c @@ -157,13 +157,12 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); * before driver shutdown. But it also seems to be caused by bugs in cardbus * bridge shutdown: shutting down the bridge before the devices using it. */ -static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, - u32 mask, u32 done, int usec) +static int handshake (void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; do { - result = ehci_readl(ehci, ptr); + result = readl (ptr); if (result == ~(u32)0) /* card removed */ return -ENODEV; result &= mask; @@ -178,19 +177,18 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, /* force HC to halt state from unknown (EHCI spec section 2.3) */ static int ehci_halt (struct ehci_hcd *ehci) { - u32 temp = ehci_readl(ehci, &ehci->regs->status); + u32 temp = readl (&ehci->regs->status); /* disable any irqs left enabled by previous code */ - ehci_writel(ehci, 0, &ehci->regs->intr_enable); + writel (0, &ehci->regs->intr_enable); if ((temp & STS_HALT) != 0) return 0; - temp = ehci_readl(ehci, &ehci->regs->command); + temp = readl (&ehci->regs->command); temp &= ~CMD_RUN; - ehci_writel(ehci, temp, &ehci->regs->command); - return handshake (ehci, &ehci->regs->status, - STS_HALT, STS_HALT, 16 * 125); + writel (temp, &ehci->regs->command); + return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125); } /* put TDI/ARC silicon into EHCI mode */ @@ -200,24 +198,23 @@ static void tdi_reset (struct ehci_hcd *ehci) u32 tmp; reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68); - tmp = ehci_readl(ehci, reg_ptr); + tmp = readl (reg_ptr); tmp |= 0x3; - ehci_writel(ehci, tmp, reg_ptr); + writel (tmp, reg_ptr); } /* reset a non-running (STS_HALT == 1) controller */ static int ehci_reset (struct ehci_hcd *ehci) { int retval; - u32 command = ehci_readl(ehci, &ehci->regs->command); + u32 command = readl (&ehci->regs->command); command |= CMD_RESET; dbg_cmd (ehci, "reset", command); - ehci_writel(ehci, command, &ehci->regs->command); + writel (command, &ehci->regs->command); ehci_to_hcd(ehci)->state = HC_STATE_HALT; ehci->next_statechange = jiffies; - retval = handshake (ehci, &ehci->regs->command, - CMD_RESET, 0, 250 * 1000); + retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000); if (retval) return retval; @@ -239,21 +236,21 @@ static void ehci_quiesce (struct ehci_hcd *ehci) #endif /* wait for any schedule enables/disables to take effect */ - temp = ehci_readl(ehci, &ehci->regs->command) << 10; + temp = readl (&ehci->regs->command) << 10; temp &= STS_ASS | STS_PSS; - if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS, + if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125) != 0) { ehci_to_hcd(ehci)->state = HC_STATE_HALT; return; } /* then disable anything that's still active */ - temp = ehci_readl(ehci, &ehci->regs->command); + temp = readl (&ehci->regs->command); temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); - ehci_writel(ehci, temp, &ehci->regs->command); + writel (temp, &ehci->regs->command); /* hardware can take 16 microframes to turn off ... */ - if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS, + if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125) != 0) { ehci_to_hcd(ehci)->state = HC_STATE_HALT; return; @@ -280,11 +277,11 @@ static void ehci_watchdog (unsigned long param) /* lost IAA irqs wedge things badly; seen with a vt8235 */ if (ehci->reclaim) { - u32 status = ehci_readl(ehci, &ehci->regs->status); + u32 status = readl (&ehci->regs->status); if (status & STS_IAA) { ehci_vdbg (ehci, "lost IAA\n"); COUNT (ehci->stats.lost_iaa); - ehci_writel(ehci, STS_IAA, &ehci->regs->status); + writel (STS_IAA, &ehci->regs->status); ehci->reclaim_ready = 1; } } @@ -312,7 +309,7 @@ ehci_shutdown (struct usb_hcd *hcd) (void) ehci_halt (ehci); /* make BIOS/etc use companion controller during reboot */ - ehci_writel(ehci, 0, &ehci->regs->configured_flag); + writel (0, &ehci->regs->configured_flag); } static void ehci_port_power (struct ehci_hcd *ehci, int is_on) @@ -382,13 +379,12 @@ static void ehci_stop (struct usb_hcd *hcd) ehci_quiesce (ehci); ehci_reset (ehci); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); + writel (0, &ehci->regs->intr_enable); spin_unlock_irq(&ehci->lock); /* let companion controllers work when we aren't */ - ehci_writel(ehci, 0, &ehci->regs->configured_flag); + writel (0, &ehci->regs->configured_flag); - remove_companion_file(ehci); remove_debug_files (ehci); /* root hub is shut down separately (first, when possible) */ @@ -406,8 +402,7 @@ static void ehci_stop (struct usb_hcd *hcd) ehci->stats.complete, ehci->stats.unlink); #endif - dbg_status (ehci, "ehci_stop completed", - ehci_readl(ehci, &ehci->regs->status)); + dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); } /* one-time init, only for memory state */ @@ -433,7 +428,7 @@ static int ehci_init(struct usb_hcd *hcd) return retval; /* controllers may cache some of the periodic schedule ... */ - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); + hcc_params = readl(&ehci->caps->hcc_params); if (HCC_ISOC_CACHE(hcc_params)) // full frame cache ehci->i_thresh = 8; else // N microframes cached @@ -501,16 +496,13 @@ static int ehci_run (struct usb_hcd *hcd) u32 temp; u32 hcc_params; - hcd->uses_new_polling = 1; - hcd->poll_rh = 0; - /* EHCI spec section 4.1 */ if ((retval = ehci_reset(ehci)) != 0) { ehci_mem_cleanup(ehci); return retval; } - ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); - ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); + writel(ehci->periodic_dma, &ehci->regs->frame_list); + writel((u32)ehci->async->qh_dma, &ehci->regs->async_next); /* * hcc_params controls whether ehci->regs->segment must (!!!) @@ -524,9 +516,9 @@ static int ehci_run (struct usb_hcd *hcd) * Scsi_Host.highmem_io, and so forth. It's readonly to all * host side drivers though. */ - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); + hcc_params = readl(&ehci->caps->hcc_params); if (HCC_64BIT_ADDR(hcc_params)) { - ehci_writel(ehci, 0, &ehci->regs->segment); + writel(0, &ehci->regs->segment); #if 0 // this is deeply broken on almost all architectures if (!dma_set_mask(hcd->self.controller, DMA_64BIT_MASK)) @@ -539,7 +531,7 @@ static int ehci_run (struct usb_hcd *hcd) // root hub will detect new devices (why?); NEC doesn't ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); ehci->command |= CMD_RUN; - ehci_writel(ehci, ehci->command, &ehci->regs->command); + writel (ehci->command, &ehci->regs->command); dbg_cmd (ehci, "init", ehci->command); /* @@ -549,25 +541,23 @@ static int ehci_run (struct usb_hcd *hcd) * and there's no companion controller unless maybe for USB OTG.) */ hcd->state = HC_STATE_RUNNING; - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + writel (FLAG_CF, &ehci->regs->configured_flag); + readl (&ehci->regs->command); /* unblock posted writes */ - temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); + temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); ehci_info (ehci, "USB %x.%x started, EHCI %x.%02x, driver %s%s\n", ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), temp >> 8, temp & 0xff, DRIVER_VERSION, ignore_oc ? ", overcurrent ignored" : ""); - ehci_writel(ehci, INTR_MASK, - &ehci->regs->intr_enable); /* Turn On Interrupts */ + writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ /* GRR this is run-once init(), being done every time the HC starts. * So long as they're part of class devices, we can't do it init() * since the class device isn't created that early. */ create_debug_files(ehci); - create_companion_file(ehci); return 0; } @@ -577,12 +567,12 @@ static int ehci_run (struct usb_hcd *hcd) static irqreturn_t ehci_irq (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 status, pcd_status = 0; + u32 status; int bh; spin_lock (&ehci->lock); - status = ehci_readl(ehci, &ehci->regs->status); + status = readl (&ehci->regs->status); /* e.g. cardbus physical eject */ if (status == ~(u32) 0) { @@ -597,8 +587,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) } /* clear (just) interrupts */ - ehci_writel(ehci, status, &ehci->regs->status); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */ + writel (status, &ehci->regs->status); + readl (&ehci->regs->command); /* unblock posted write */ bh = 0; #ifdef EHCI_VERBOSE_DEBUG @@ -627,15 +617,13 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* remote wakeup [4.3.1] */ if (status & STS_PCD) { unsigned i = HCS_N_PORTS (ehci->hcs_params); - pcd_status = status; /* resume root hub? */ - if (!(ehci_readl(ehci, &ehci->regs->command) & CMD_RUN)) + if (!(readl(&ehci->regs->command) & CMD_RUN)) usb_hcd_resume_root_hub(hcd); while (i--) { - int pstatus = ehci_readl(ehci, - &ehci->regs->port_status [i]); + int pstatus = readl (&ehci->regs->port_status [i]); if (pstatus & PORT_OWNER) continue; @@ -655,15 +643,14 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* PCI errors [4.15.2.4] */ if (unlikely ((status & STS_FATAL) != 0)) { /* bogus "fatal" IRQs appear on some chips... why? */ - status = ehci_readl(ehci, &ehci->regs->status); - dbg_cmd (ehci, "fatal", ehci_readl(ehci, - &ehci->regs->command)); + status = readl (&ehci->regs->status); + dbg_cmd (ehci, "fatal", readl (&ehci->regs->command)); dbg_status (ehci, "fatal", status); if (status & STS_HALT) { ehci_err (ehci, "fatal error\n"); dead: ehci_reset (ehci); - ehci_writel(ehci, 0, &ehci->regs->configured_flag); + writel (0, &ehci->regs->configured_flag); /* generic layer kills/unlinks all urbs, then * uses ehci_stop to clean up the rest */ @@ -674,8 +661,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) if (bh) ehci_work (ehci); spin_unlock (&ehci->lock); - if (pcd_status & STS_PCD) - usb_hcd_poll_rh_status(hcd); return IRQ_HANDLED; } @@ -888,8 +873,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) static int ehci_get_frame (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) % - ehci->periodic_size; + return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size; } /*-------------------------------------------------------------------------*/ @@ -915,13 +899,7 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver #endif -#ifdef CONFIG_PPC_PS3 -#include "ehci-ps3.c" -#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_sb_driver -#endif - -#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ - !defined(PS3_SYSTEM_BUS_DRIVER) +#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) #error "missing bus glue for ehci-hcd" #endif @@ -946,20 +924,6 @@ static int __init ehci_hcd_init(void) #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); #endif - return retval; - } -#endif - -#ifdef PS3_SYSTEM_BUS_DRIVER - retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER); - if (retval < 0) { -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); -#endif -#ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); -#endif - return retval; } #endif @@ -975,9 +939,6 @@ static void __exit ehci_hcd_cleanup(void) #ifdef PCI_DRIVER pci_unregister_driver(&PCI_DRIVER); #endif -#ifdef PS3_SYSTEM_BUS_DRIVER - ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); -#endif } module_exit(ehci_hcd_cleanup); diff --git a/trunk/drivers/usb/host/ehci-hub.c b/trunk/drivers/usb/host/ehci-hub.c index 0d83c6df1a3b..bfe5f307cba6 100644 --- a/trunk/drivers/usb/host/ehci-hub.c +++ b/trunk/drivers/usb/host/ehci-hub.c @@ -47,7 +47,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ehci_quiesce (ehci); hcd->state = HC_STATE_QUIESCING; } - ehci->command = ehci_readl(ehci, &ehci->regs->command); + ehci->command = readl (&ehci->regs->command); if (ehci->reclaim) ehci->reclaim_ready = 1; ehci_work(ehci); @@ -60,7 +60,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ehci->bus_suspended = 0; while (port--) { u32 __iomem *reg = &ehci->regs->port_status [port]; - u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; + u32 t1 = readl (reg) & ~PORT_RWC_BITS; u32 t2 = t1; /* keep track of which ports we suspend */ @@ -79,7 +79,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) if (t1 != t2) { ehci_vdbg (ehci, "port %d, %08x -> %08x\n", port + 1, t1, t2); - ehci_writel(ehci, t2, reg); + writel (t2, reg); } } @@ -92,8 +92,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) mask = INTR_MASK; if (!device_may_wakeup(&hcd->self.root_hub->dev)) mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); + writel(mask, &ehci->regs->intr_enable); + readl(&ehci->regs->intr_enable); ehci->next_statechange = jiffies + msecs_to_jiffies(10); spin_unlock_irq (&ehci->lock); @@ -118,26 +118,26 @@ static int ehci_bus_resume (struct usb_hcd *hcd) * the last user of the controller, not reset/pm hardware keeping * state we gave to it. */ - temp = ehci_readl(ehci, &ehci->regs->intr_enable); + temp = readl(&ehci->regs->intr_enable); ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss"); /* at least some APM implementations will try to deliver * IRQs right away, so delay them until we're ready. */ - ehci_writel(ehci, 0, &ehci->regs->intr_enable); + writel(0, &ehci->regs->intr_enable); /* re-init operational registers */ - ehci_writel(ehci, 0, &ehci->regs->segment); - ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); - ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next); + writel(0, &ehci->regs->segment); + writel(ehci->periodic_dma, &ehci->regs->frame_list); + writel((u32) ehci->async->qh_dma, &ehci->regs->async_next); /* restore CMD_RUN, framelist size, and irq threshold */ - ehci_writel(ehci, ehci->command, &ehci->regs->command); + writel (ehci->command, &ehci->regs->command); /* manually resume the ports we suspended during bus_suspend() */ i = HCS_N_PORTS (ehci->hcs_params); while (i--) { - temp = ehci_readl(ehci, &ehci->regs->port_status [i]); + temp = readl (&ehci->regs->port_status [i]); temp &= ~(PORT_RWC_BITS | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); if (test_bit(i, &ehci->bus_suspended) && @@ -145,20 +145,20 @@ static int ehci_bus_resume (struct usb_hcd *hcd) ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); temp |= PORT_RESUME; } - ehci_writel(ehci, temp, &ehci->regs->port_status [i]); + writel (temp, &ehci->regs->port_status [i]); } i = HCS_N_PORTS (ehci->hcs_params); mdelay (20); while (i--) { - temp = ehci_readl(ehci, &ehci->regs->port_status [i]); + temp = readl (&ehci->regs->port_status [i]); if (test_bit(i, &ehci->bus_suspended) && (temp & PORT_SUSPEND)) { temp &= ~(PORT_RWC_BITS | PORT_RESUME); - ehci_writel(ehci, temp, &ehci->regs->port_status [i]); + writel (temp, &ehci->regs->port_status [i]); ehci_vdbg (ehci, "resumed port %d\n", i + 1); } } - (void) ehci_readl(ehci, &ehci->regs->command); + (void) readl (&ehci->regs->command); /* maybe re-activate the schedule(s) */ temp = 0; @@ -168,14 +168,14 @@ static int ehci_bus_resume (struct usb_hcd *hcd) temp |= CMD_PSE; if (temp) { ehci->command |= temp; - ehci_writel(ehci, ehci->command, &ehci->regs->command); + writel (ehci->command, &ehci->regs->command); } ehci->next_statechange = jiffies + msecs_to_jiffies(5); hcd->state = HC_STATE_RUNNING; /* Now we can safely re-enable irqs */ - ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); + writel(INTR_MASK, &ehci->regs->intr_enable); spin_unlock_irq (&ehci->lock); return 0; @@ -188,109 +188,11 @@ static int ehci_bus_resume (struct usb_hcd *hcd) #endif /* CONFIG_PM */ -/*-------------------------------------------------------------------------*/ - -/* Display the ports dedicated to the companion controller */ -static ssize_t show_companion(struct class_device *class_dev, char *buf) -{ - struct ehci_hcd *ehci; - int nports, index, n; - int count = PAGE_SIZE; - char *ptr = buf; - - ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev))); - nports = HCS_N_PORTS(ehci->hcs_params); - - for (index = 0; index < nports; ++index) { - if (test_bit(index, &ehci->companion_ports)) { - n = scnprintf(ptr, count, "%d\n", index + 1); - ptr += n; - count -= n; - } - } - return ptr - buf; -} - -/* - * Dedicate or undedicate a port to the companion controller. - * Syntax is "[-]portnum", where a leading '-' sign means - * return control of the port to the EHCI controller. - */ -static ssize_t store_companion(struct class_device *class_dev, - const char *buf, size_t count) -{ - struct ehci_hcd *ehci; - int portnum, new_owner, try; - u32 __iomem *status_reg; - u32 port_status; - - ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev))); - new_owner = PORT_OWNER; /* Owned by companion */ - if (sscanf(buf, "%d", &portnum) != 1) - return -EINVAL; - if (portnum < 0) { - portnum = - portnum; - new_owner = 0; /* Owned by EHCI */ - } - if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) - return -ENOENT; - status_reg = &ehci->regs->port_status[--portnum]; - if (new_owner) - set_bit(portnum, &ehci->companion_ports); - else - clear_bit(portnum, &ehci->companion_ports); - - /* - * The controller won't set the OWNER bit if the port is - * enabled, so this loop will sometimes require at least two - * iterations: one to disable the port and one to set OWNER. - */ - - for (try = 4; try > 0; --try) { - spin_lock_irq(&ehci->lock); - port_status = ehci_readl(ehci, status_reg); - if ((port_status & PORT_OWNER) == new_owner - || (port_status & (PORT_OWNER | PORT_CONNECT)) - == 0) - try = 0; - else { - port_status ^= PORT_OWNER; - port_status &= ~(PORT_PE | PORT_RWC_BITS); - ehci_writel(ehci, port_status, status_reg); - } - spin_unlock_irq(&ehci->lock); - if (try > 1) - msleep(5); - } - return count; -} -static CLASS_DEVICE_ATTR(companion, 0644, show_companion, store_companion); - -static inline void create_companion_file(struct ehci_hcd *ehci) -{ - int i; - - /* with integrated TT there is no companion! */ - if (!ehci_is_TDI(ehci)) - i = class_device_create_file(ehci_to_hcd(ehci)->self.class_dev, - &class_device_attr_companion); -} - -static inline void remove_companion_file(struct ehci_hcd *ehci) -{ - /* with integrated TT there is no companion! */ - if (!ehci_is_TDI(ehci)) - class_device_remove_file(ehci_to_hcd(ehci)->self.class_dev, - &class_device_attr_companion); -} - - /*-------------------------------------------------------------------------*/ static int check_reset_complete ( struct ehci_hcd *ehci, int index, - u32 __iomem *status_reg, int port_status ) { if (!(port_status & PORT_CONNECT)) { @@ -315,7 +217,7 @@ static int check_reset_complete ( // what happens if HCS_N_CC(params) == 0 ? port_status |= PORT_OWNER; port_status &= ~PORT_RWC_BITS; - ehci_writel(ehci, port_status, status_reg); + writel (port_status, &ehci->regs->port_status [index]); } else ehci_dbg (ehci, "port %d high speed\n", index + 1); @@ -366,21 +268,22 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) /* port N changes (bit N)? */ spin_lock_irqsave (&ehci->lock, flags); for (i = 0; i < ports; i++) { - temp = ehci_readl(ehci, &ehci->regs->port_status [i]); - - /* - * Return status information even for ports with OWNER set. - * Otherwise khubd wouldn't see the disconnect event when a - * high-speed device is switched over to the companion - * controller by the user. - */ - + temp = readl (&ehci->regs->port_status [i]); + if (temp & PORT_OWNER) { + /* don't report this in GetPortStatus */ + if (temp & PORT_CSC) { + temp &= ~PORT_RWC_BITS; + temp |= PORT_CSC; + writel (temp, &ehci->regs->port_status [i]); + } + continue; + } if (!(temp & PORT_CONNECT)) ehci->reset_done [i] = 0; if ((temp & mask) != 0 || ((temp & PORT_RESUME) != 0 - && time_after_eq(jiffies, - ehci->reset_done[i]))) { + && time_after (jiffies, + ehci->reset_done [i]))) { if (i < 7) buf [0] |= 1 << (i + 1); else @@ -442,7 +345,6 @@ static int ehci_hub_control ( ) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); int ports = HCS_N_PORTS (ehci->hcs_params); - u32 __iomem *status_reg = &ehci->regs->port_status[wIndex - 1]; u32 temp, status; unsigned long flags; int retval = 0; @@ -471,22 +373,18 @@ static int ehci_hub_control ( if (!wIndex || wIndex > ports) goto error; wIndex--; - temp = ehci_readl(ehci, status_reg); - - /* - * Even if OWNER is set, so the port is owned by the - * companion controller, khubd needs to be able to clear - * the port-change status bits (especially - * USB_PORT_FEAT_C_CONNECTION). - */ + temp = readl (&ehci->regs->port_status [wIndex]); + if (temp & PORT_OWNER) + break; switch (wValue) { case USB_PORT_FEAT_ENABLE: - ehci_writel(ehci, temp & ~PORT_PE, status_reg); + writel (temp & ~PORT_PE, + &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_C_ENABLE: - ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC, - status_reg); + writel((temp & ~PORT_RWC_BITS) | PORT_PEC, + &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_SUSPEND: if (temp & PORT_RESET) @@ -498,8 +396,8 @@ static int ehci_hub_control ( goto error; /* resume signaling for 20 msec */ temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); - ehci_writel(ehci, temp | PORT_RESUME, - status_reg); + writel (temp | PORT_RESUME, + &ehci->regs->port_status [wIndex]); ehci->reset_done [wIndex] = jiffies + msecs_to_jiffies (20); } @@ -509,17 +407,16 @@ static int ehci_hub_control ( break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) - ehci_writel(ehci, - temp & ~(PORT_RWC_BITS | PORT_POWER), - status_reg); + writel (temp & ~(PORT_RWC_BITS | PORT_POWER), + &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_C_CONNECTION: - ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, - status_reg); + writel((temp & ~PORT_RWC_BITS) | PORT_CSC, + &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_C_OVER_CURRENT: - ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC, - status_reg); + writel((temp & ~PORT_RWC_BITS) | PORT_OCC, + &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_C_RESET: /* GetPortStatus clears reset */ @@ -527,7 +424,7 @@ static int ehci_hub_control ( default: goto error; } - ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */ + readl (&ehci->regs->command); /* unblock posted write */ break; case GetHubDescriptor: ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) @@ -543,7 +440,7 @@ static int ehci_hub_control ( goto error; wIndex--; status = 0; - temp = ehci_readl(ehci, status_reg); + temp = readl (&ehci->regs->port_status [wIndex]); // wPortChange bits if (temp & PORT_CSC) @@ -554,55 +451,42 @@ static int ehci_hub_control ( status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; /* whoever resumes must GetPortStatus to complete it!! */ - if (temp & PORT_RESUME) { - - /* Remote Wakeup received? */ - if (!ehci->reset_done[wIndex]) { - /* resume signaling for 20 msec */ - ehci->reset_done[wIndex] = jiffies - + msecs_to_jiffies(20); - /* check the port again */ - mod_timer(&ehci_to_hcd(ehci)->rh_timer, - ehci->reset_done[wIndex]); - } + if ((temp & PORT_RESUME) + && time_after (jiffies, + ehci->reset_done [wIndex])) { + status |= 1 << USB_PORT_FEAT_C_SUSPEND; + ehci->reset_done [wIndex] = 0; - /* resume completed? */ - else if (time_after_eq(jiffies, - ehci->reset_done[wIndex])) { - status |= 1 << USB_PORT_FEAT_C_SUSPEND; - ehci->reset_done[wIndex] = 0; - - /* stop resume signaling */ - temp = ehci_readl(ehci, status_reg); - ehci_writel(ehci, - temp & ~(PORT_RWC_BITS | PORT_RESUME), - status_reg); - retval = handshake(ehci, status_reg, - PORT_RESUME, 0, 2000 /* 2msec */); - if (retval != 0) { - ehci_err(ehci, - "port %d resume error %d\n", - wIndex + 1, retval); - goto error; - } - temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); + /* stop resume signaling */ + temp = readl (&ehci->regs->port_status [wIndex]); + writel (temp & ~(PORT_RWC_BITS | PORT_RESUME), + &ehci->regs->port_status [wIndex]); + retval = handshake ( + &ehci->regs->port_status [wIndex], + PORT_RESUME, 0, 2000 /* 2msec */); + if (retval != 0) { + ehci_err (ehci, "port %d resume error %d\n", + wIndex + 1, retval); + goto error; } + temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); } /* whoever resets must GetPortStatus to complete it!! */ if ((temp & PORT_RESET) - && time_after_eq(jiffies, - ehci->reset_done[wIndex])) { + && time_after (jiffies, + ehci->reset_done [wIndex])) { status |= 1 << USB_PORT_FEAT_C_RESET; ehci->reset_done [wIndex] = 0; /* force reset to complete */ - ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET), - status_reg); + writel (temp & ~(PORT_RWC_BITS | PORT_RESET), + &ehci->regs->port_status [wIndex]); /* REVISIT: some hardware needs 550+ usec to clear * this bit; seems too long to spin routinely... */ - retval = handshake(ehci, status_reg, + retval = handshake ( + &ehci->regs->port_status [wIndex], PORT_RESET, 0, 750); if (retval != 0) { ehci_err (ehci, "port %d reset error %d\n", @@ -611,41 +495,28 @@ static int ehci_hub_control ( } /* see what we found out */ - temp = check_reset_complete (ehci, wIndex, status_reg, - ehci_readl(ehci, status_reg)); + temp = check_reset_complete (ehci, wIndex, + readl (&ehci->regs->port_status [wIndex])); } - /* transfer dedicated ports to the companion hc */ - if ((temp & PORT_CONNECT) && - test_bit(wIndex, &ehci->companion_ports)) { - temp &= ~PORT_RWC_BITS; - temp |= PORT_OWNER; - ehci_writel(ehci, temp, status_reg); - ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1); - temp = ehci_readl(ehci, status_reg); - } - - /* - * Even if OWNER is set, there's no harm letting khubd - * see the wPortStatus values (they should all be 0 except - * for PORT_POWER anyway). - */ - - if (temp & PORT_CONNECT) { - status |= 1 << USB_PORT_FEAT_CONNECTION; - // status may be from integrated TT - status |= ehci_port_speed(ehci, temp); + // don't show wPortStatus if it's owned by a companion hc + if (!(temp & PORT_OWNER)) { + if (temp & PORT_CONNECT) { + status |= 1 << USB_PORT_FEAT_CONNECTION; + // status may be from integrated TT + status |= ehci_port_speed(ehci, temp); + } + if (temp & PORT_PE) + status |= 1 << USB_PORT_FEAT_ENABLE; + if (temp & (PORT_SUSPEND|PORT_RESUME)) + status |= 1 << USB_PORT_FEAT_SUSPEND; + if (temp & PORT_OC) + status |= 1 << USB_PORT_FEAT_OVER_CURRENT; + if (temp & PORT_RESET) + status |= 1 << USB_PORT_FEAT_RESET; + if (temp & PORT_POWER) + status |= 1 << USB_PORT_FEAT_POWER; } - if (temp & PORT_PE) - status |= 1 << USB_PORT_FEAT_ENABLE; - if (temp & (PORT_SUSPEND|PORT_RESUME)) - status |= 1 << USB_PORT_FEAT_SUSPEND; - if (temp & PORT_OC) - status |= 1 << USB_PORT_FEAT_OVER_CURRENT; - if (temp & PORT_RESET) - status |= 1 << USB_PORT_FEAT_RESET; - if (temp & PORT_POWER) - status |= 1 << USB_PORT_FEAT_POWER; #ifndef EHCI_VERBOSE_DEBUG if (status & ~0xffff) /* only if wPortChange is interesting */ @@ -670,7 +541,7 @@ static int ehci_hub_control ( if (!wIndex || wIndex > ports) goto error; wIndex--; - temp = ehci_readl(ehci, status_reg); + temp = readl (&ehci->regs->port_status [wIndex]); if (temp & PORT_OWNER) break; @@ -684,12 +555,13 @@ static int ehci_hub_control ( goto error; if (device_may_wakeup(&hcd->self.root_hub->dev)) temp |= PORT_WAKE_BITS; - ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); + writel (temp | PORT_SUSPEND, + &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) - ehci_writel(ehci, temp | PORT_POWER, - status_reg); + writel (temp | PORT_POWER, + &ehci->regs->port_status [wIndex]); break; case USB_PORT_FEAT_RESET: if (temp & PORT_RESUME) @@ -717,7 +589,7 @@ static int ehci_hub_control ( ehci->reset_done [wIndex] = jiffies + msecs_to_jiffies (50); } - ehci_writel(ehci, temp, status_reg); + writel (temp, &ehci->regs->port_status [wIndex]); break; /* For downstream facing ports (these): one hub port is put @@ -732,13 +604,13 @@ static int ehci_hub_control ( ehci_quiesce(ehci); ehci_halt(ehci); temp |= selector << 16; - ehci_writel(ehci, temp, status_reg); + writel (temp, &ehci->regs->port_status [wIndex]); break; default: goto error; } - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + readl (&ehci->regs->command); /* unblock posted writes */ break; default: diff --git a/trunk/drivers/usb/host/ehci-pci.c b/trunk/drivers/usb/host/ehci-pci.c index 12edc723ec73..4bc7970ba3ef 100644 --- a/trunk/drivers/usb/host/ehci-pci.c +++ b/trunk/drivers/usb/host/ehci-pci.c @@ -38,7 +38,7 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) if ((temp & (3 << 13)) == (1 << 13)) { temp &= 0x1fff; ehci->debug = ehci_to_hcd(ehci)->regs + temp; - temp = ehci_readl(ehci, &ehci->debug->control); + temp = readl(&ehci->debug->control); ehci_info(ehci, "debug port %d%s\n", HCS_DEBUG_PORT(ehci->hcs_params), (temp & DBGP_ENABLED) @@ -71,24 +71,8 @@ static int ehci_pci_setup(struct usb_hcd *hcd) u32 temp; int retval; - switch (pdev->vendor) { - case PCI_VENDOR_ID_TOSHIBA_2: - /* celleb's companion chip */ - if (pdev->device == 0x01b5) { -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - ehci->big_endian_mmio = 1; -#else - ehci_warn(ehci, - "unsupported big endian Toshiba quirk\n"); -#endif - } - break; - } - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); - + ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); @@ -117,7 +101,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) } /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); + ehci->hcs_params = readl(&ehci->caps->hcs_params); retval = ehci_halt(ehci); if (retval) @@ -251,8 +235,8 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) rc = -EINVAL; goto bail; } - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - (void)ehci_readl(ehci, &ehci->regs->intr_enable); + writel (0, &ehci->regs->intr_enable); + (void)readl(&ehci->regs->intr_enable); /* make sure snapshot being resumed re-enumerates everything */ if (message.event == PM_EVENT_PRETHAW) { @@ -286,13 +270,13 @@ static int ehci_pci_resume(struct usb_hcd *hcd) /* If CF is still set, we maintained PCI Vaux power. * Just undo the effect of ehci_pci_suspend(). */ - if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { + if (readl(&ehci->regs->configured_flag) == FLAG_CF) { int mask = INTR_MASK; if (!device_may_wakeup(&hcd->self.root_hub->dev)) mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); + writel(mask, &ehci->regs->intr_enable); + readl(&ehci->regs->intr_enable); return 0; } @@ -316,9 +300,9 @@ static int ehci_pci_resume(struct usb_hcd *hcd) /* here we "know" root ports should always stay powered */ ehci_port_power(ehci, 1); - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + writel(ehci->command, &ehci->regs->command); + writel(FLAG_CF, &ehci->regs->configured_flag); + readl(&ehci->regs->command); /* unblock posted writes */ hcd->state = HC_STATE_SUSPENDED; return 0; diff --git a/trunk/drivers/usb/host/ehci-ps3.c b/trunk/drivers/usb/host/ehci-ps3.c deleted file mode 100644 index 371f194a9d39..000000000000 --- a/trunk/drivers/usb/host/ehci-ps3.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * PS3 EHCI Host Controller driver - * - * Copyright (C) 2006 Sony Computer Entertainment Inc. - * Copyright 2006 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 - -static int ps3_ehci_hc_reset(struct usb_hcd *hcd) -{ - int result; - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - ehci->big_endian_mmio = 1; - - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, - &ehci->caps->hc_capbase)); - - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - result = ehci_halt(ehci); - - if (result) - return result; - - result = ehci_init(hcd); - - if (result) - return result; - - ehci_port_power(ehci, 0); - - return result; -} - -static const struct hc_driver ps3_ehci_hc_driver = { - .description = hcd_name, - .product_desc = "PS3 EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - .reset = ps3_ehci_hc_reset, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .get_frame_number = ehci_get_frame, - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, -#if defined(CONFIG_PM) - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, -#endif -}; - -#if !defined(DEBUG) -#undef dev_dbg -static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg( - const struct device *_dev, const char *fmt, ...) {return 0;} -#endif - - -static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) -{ - int result; - struct usb_hcd *hcd; - unsigned int virq; - static u64 dummy_mask = DMA_32BIT_MASK; - - if (usb_disabled()) { - result = -ENODEV; - goto fail_start; - } - - result = ps3_mmio_region_create(dev->m_region); - - if (result) { - dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", - __func__, __LINE__); - result = -EPERM; - goto fail_mmio; - } - - 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); - - if (result) { - dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n", - __func__, __LINE__, virq); - result = -EPERM; - goto fail_irq; - } - - dev->core.power.power_state = PMSG_ON; - dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */ - - hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev->core.bus_id); - - if (!hcd) { - dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__, - __LINE__); - result = -ENOMEM; - goto fail_create_hcd; - } - - hcd->rsrc_start = dev->m_region->lpar_addr; - hcd->rsrc_len = dev->m_region->len; - hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); - - if (!hcd->regs) { - dev_dbg(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - result = -EPERM; - goto fail_ioremap; - } - - dev_dbg(&dev->core, "%s:%d: hcd->rsrc_start %lxh\n", __func__, __LINE__, - (unsigned long)hcd->rsrc_start); - dev_dbg(&dev->core, "%s:%d: hcd->rsrc_len %lxh\n", __func__, __LINE__, - (unsigned long)hcd->rsrc_len); - dev_dbg(&dev->core, "%s:%d: hcd->regs %lxh\n", __func__, __LINE__, - (unsigned long)hcd->regs); - dev_dbg(&dev->core, "%s:%d: virq %lu\n", __func__, __LINE__, - (unsigned long)virq); - - ps3_system_bus_set_driver_data(dev, hcd); - - result = usb_add_hcd(hcd, virq, IRQF_DISABLED); - - if (result) { - dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", - __func__, __LINE__, result); - goto fail_add_hcd; - } - - return result; - -fail_add_hcd: - iounmap(hcd->regs); -fail_ioremap: - usb_put_hcd(hcd); -fail_create_hcd: - ps3_free_io_irq(virq); -fail_irq: - ps3_free_mmio_region(dev->m_region); -fail_mmio: -fail_start: - return result; -} - -static int ps3_ehci_sb_remove(struct ps3_system_bus_device *dev) -{ - struct usb_hcd *hcd = - (struct usb_hcd *)ps3_system_bus_get_driver_data(dev); - - usb_put_hcd(hcd); - ps3_system_bus_set_driver_data(dev, NULL); - - return 0; -} - -MODULE_ALIAS("ps3-ehci"); - -static struct ps3_system_bus_driver ps3_ehci_sb_driver = { - .match_id = PS3_MATCH_ID_EHCI, - .core = { - .name = "ps3-ehci-driver", - }, - .probe = ps3_ehci_sb_probe, - .remove = ps3_ehci_sb_remove, -}; diff --git a/trunk/drivers/usb/host/ehci-q.c b/trunk/drivers/usb/host/ehci-q.c index e7fbbd00e7cd..62e46dc60e86 100644 --- a/trunk/drivers/usb/host/ehci-q.c +++ b/trunk/drivers/usb/host/ehci-q.c @@ -789,14 +789,13 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) head = ehci->async; timer_action_done (ehci, TIMER_ASYNC_OFF); if (!head->qh_next.qh) { - u32 cmd = ehci_readl(ehci, &ehci->regs->command); + u32 cmd = readl (&ehci->regs->command); if (!(cmd & CMD_ASE)) { /* in case a clear of CMD_ASE didn't take yet */ - (void)handshake(ehci, &ehci->regs->status, - STS_ASS, 0, 150); + (void) handshake (&ehci->regs->status, STS_ASS, 0, 150); cmd |= CMD_ASE | CMD_RUN; - ehci_writel(ehci, cmd, &ehci->regs->command); + writel (cmd, &ehci->regs->command); ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; /* posted write need not be known to HC yet ... */ } @@ -1008,7 +1007,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) { - int cmd = ehci_readl(ehci, &ehci->regs->command); + int cmd = readl (&ehci->regs->command); struct ehci_qh *prev; #ifdef DEBUG @@ -1026,8 +1025,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) if (ehci_to_hcd(ehci)->state != HC_STATE_HALT && !ehci->reclaim) { /* ... and CMD_IAAD clear */ - ehci_writel(ehci, cmd & ~CMD_ASE, - &ehci->regs->command); + writel (cmd & ~CMD_ASE, &ehci->regs->command); wmb (); // handshake later, if we need to timer_action_done (ehci, TIMER_ASYNC_OFF); @@ -1056,8 +1054,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) ehci->reclaim_ready = 0; cmd |= CMD_IAAD; - ehci_writel(ehci, cmd, &ehci->regs->command); - (void)ehci_readl(ehci, &ehci->regs->command); + writel (cmd, &ehci->regs->command); + (void) readl (&ehci->regs->command); timer_action (ehci, TIMER_IAA_WATCHDOG); } diff --git a/trunk/drivers/usb/host/ehci-sched.c b/trunk/drivers/usb/host/ehci-sched.c index 7b5ae7111f23..65c402a0fa7a 100644 --- a/trunk/drivers/usb/host/ehci-sched.c +++ b/trunk/drivers/usb/host/ehci-sched.c @@ -433,20 +433,20 @@ static int enable_periodic (struct ehci_hcd *ehci) /* did clearing PSE did take effect yet? * takes effect only at frame boundaries... */ - status = handshake(ehci, &ehci->regs->status, STS_PSS, 0, 9 * 125); + status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125); if (status != 0) { ehci_to_hcd(ehci)->state = HC_STATE_HALT; return status; } - cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE; - ehci_writel(ehci, cmd, &ehci->regs->command); + cmd = readl (&ehci->regs->command) | CMD_PSE; + writel (cmd, &ehci->regs->command); /* posted write ... PSS happens later */ ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; /* make sure ehci_work scans these */ - ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index) - % (ehci->periodic_size << 3); + ehci->next_uframe = readl (&ehci->regs->frame_index) + % (ehci->periodic_size << 3); return 0; } @@ -458,14 +458,14 @@ static int disable_periodic (struct ehci_hcd *ehci) /* did setting PSE not take effect yet? * takes effect only at frame boundaries... */ - status = handshake(ehci, &ehci->regs->status, STS_PSS, STS_PSS, 9 * 125); + status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125); if (status != 0) { ehci_to_hcd(ehci)->state = HC_STATE_HALT; return status; } - cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE; - ehci_writel(ehci, cmd, &ehci->regs->command); + cmd = readl (&ehci->regs->command) & ~CMD_PSE; + writel (cmd, &ehci->regs->command); /* posted write ... */ ehci->next_uframe = -1; @@ -1336,7 +1336,7 @@ iso_stream_schedule ( goto fail; } - now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; + now = readl (&ehci->regs->frame_index) % mod; /* when's the last uframe this urb could start? */ max = now + mod; @@ -2088,7 +2088,7 @@ scan_periodic (struct ehci_hcd *ehci) */ now_uframe = ehci->next_uframe; if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) - clock = ehci_readl(ehci, &ehci->regs->frame_index); + clock = readl (&ehci->regs->frame_index); else clock = now_uframe + mod - 1; clock %= mod; @@ -2213,7 +2213,7 @@ scan_periodic (struct ehci_hcd *ehci) if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) break; ehci->next_uframe = now_uframe; - now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; + now = readl (&ehci->regs->frame_index) % mod; if (now_uframe == now) break; diff --git a/trunk/drivers/usb/host/ehci.h b/trunk/drivers/usb/host/ehci.h index ec0da0343be4..74dbc6c8228f 100644 --- a/trunk/drivers/usb/host/ehci.h +++ b/trunk/drivers/usb/host/ehci.h @@ -74,11 +74,7 @@ struct ehci_hcd { /* one per controller */ /* per root hub port */ unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; - /* bit vectors (one bit per port) */ - unsigned long bus_suspended; /* which ports were - already suspended at the start of a bus suspend */ - unsigned long companion_ports; /* which ports are - dedicated to the companion controller */ + unsigned long bus_suspended; /* per-HC memory pools (could be per-bus, but ...) */ struct dma_pool *qh_pool; /* qh per active urb */ @@ -96,7 +92,6 @@ struct ehci_hcd { /* one per controller */ unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ unsigned no_selective_suspend:1; unsigned has_fsl_port_bug:1; /* FreeScale */ - unsigned big_endian_mmio:1; u8 sbrn; /* packed release number */ @@ -656,45 +651,6 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) #define ehci_has_fsl_portno_bug(e) (0) #endif -/* - * While most USB host controllers implement their registers in - * little-endian format, a minority (celleb companion chip) implement - * them in big endian format. - * - * This attempts to support either format at compile time without a - * runtime penalty, or both formats with the additional overhead - * of checking a flag bit. - */ - -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO -#define ehci_big_endian_mmio(e) ((e)->big_endian_mmio) -#else -#define ehci_big_endian_mmio(e) 0 -#endif - -static inline unsigned int ehci_readl (const struct ehci_hcd *ehci, - __u32 __iomem * regs) -{ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - return ehci_big_endian_mmio(ehci) ? - readl_be((__force u32 *)regs) : - readl((__force u32 *)regs); -#else - return readl((__force u32 *)regs); -#endif -} - -static inline void ehci_writel (const struct ehci_hcd *ehci, - const unsigned int val, __u32 __iomem *regs) -{ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - ehci_big_endian_mmio(ehci) ? - writel_be(val, (__force u32 *)regs) : - writel(val, (__force u32 *)regs); -#else - writel(val, (__force u32 *)regs); -#endif -} /*-------------------------------------------------------------------------*/ diff --git a/trunk/drivers/usb/host/ohci-at91.c b/trunk/drivers/usb/host/ohci-at91.c index 930346487278..cc405512fa1c 100644 --- a/trunk/drivers/usb/host/ohci-at91.c +++ b/trunk/drivers/usb/host/ohci-at91.c @@ -170,6 +170,7 @@ static int usb_hcd_at91_remove(struct usb_hcd *hcd, at91_stop_hc(pdev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + disable_irq_wake(hcd->irq); clk_put(fclk); clk_put(iclk); @@ -270,6 +271,8 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) if (device_may_wakeup(&pdev->dev)) enable_irq_wake(hcd->irq); + else + disable_irq_wake(hcd->irq); /* * The integrated transceivers seem unable to notice disconnect, @@ -290,11 +293,6 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) { - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(hcd->irq); - if (!clocked) { clk_enable(iclk); clk_enable(fclk); @@ -322,3 +320,18 @@ static struct platform_driver ohci_hcd_at91_driver = { }, }; +static int __init ohci_hcd_at91_init (void) +{ + if (usb_disabled()) + return -ENODEV; + + return platform_driver_register(&ohci_hcd_at91_driver); +} + +static void __exit ohci_hcd_at91_cleanup (void) +{ + platform_driver_unregister(&ohci_hcd_at91_driver); +} + +module_init (ohci_hcd_at91_init); +module_exit (ohci_hcd_at91_cleanup); diff --git a/trunk/drivers/usb/host/ohci-au1xxx.c b/trunk/drivers/usb/host/ohci-au1xxx.c index 663a0600b6e7..e70b2430e2a9 100644 --- a/trunk/drivers/usb/host/ohci-au1xxx.c +++ b/trunk/drivers/usb/host/ohci-au1xxx.c @@ -345,3 +345,19 @@ static struct platform_driver ohci_hcd_au1xxx_driver = { }, }; +static int __init ohci_hcd_au1xxx_init (void) +{ + pr_debug (DRIVER_INFO " (Au1xxx)"); + pr_debug ("block sizes: ed %d td %d\n", + sizeof (struct ed), sizeof (struct td)); + + return platform_driver_register(&ohci_hcd_au1xxx_driver); +} + +static void __exit ohci_hcd_au1xxx_cleanup (void) +{ + platform_driver_unregister(&ohci_hcd_au1xxx_driver); +} + +module_init (ohci_hcd_au1xxx_init); +module_exit (ohci_hcd_au1xxx_cleanup); diff --git a/trunk/drivers/usb/host/ohci-ep93xx.c b/trunk/drivers/usb/host/ohci-ep93xx.c index 44c60fba76e1..3348b07f0fe5 100644 --- a/trunk/drivers/usb/host/ohci-ep93xx.c +++ b/trunk/drivers/usb/host/ohci-ep93xx.c @@ -214,3 +214,15 @@ static struct platform_driver ohci_hcd_ep93xx_driver = { }, }; +static int __init ohci_hcd_ep93xx_init(void) +{ + return platform_driver_register(&ohci_hcd_ep93xx_driver); +} + +static void __exit ohci_hcd_ep93xx_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_ep93xx_driver); +} + +module_init(ohci_hcd_ep93xx_init); +module_exit(ohci_hcd_ep93xx_cleanup); diff --git a/trunk/drivers/usb/host/ohci-hcd.c b/trunk/drivers/usb/host/ohci-hcd.c index fa6a7ceaa0db..c1c1d871aba4 100644 --- a/trunk/drivers/usb/host/ohci-hcd.c +++ b/trunk/drivers/usb/host/ohci-hcd.c @@ -855,167 +855,63 @@ MODULE_LICENSE ("GPL"); #ifdef CONFIG_PCI #include "ohci-pci.c" -#define PCI_DRIVER ohci_pci_driver #endif #ifdef CONFIG_SA1111 #include "ohci-sa1111.c" -#define SA1111_DRIVER ohci_hcd_sa1111_driver #endif #ifdef CONFIG_ARCH_S3C2410 #include "ohci-s3c2410.c" -#define PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif #ifdef CONFIG_ARCH_OMAP #include "ohci-omap.c" -#define PLATFORM_DRIVER ohci_hcd_omap_driver #endif #ifdef CONFIG_ARCH_LH7A404 #include "ohci-lh7a404.c" -#define PLATFORM_DRIVER ohci_hcd_lh7a404_driver #endif #ifdef CONFIG_PXA27x #include "ohci-pxa27x.c" -#define PLATFORM_DRIVER ohci_hcd_pxa27x_driver #endif #ifdef CONFIG_ARCH_EP93XX #include "ohci-ep93xx.c" -#define PLATFORM_DRIVER ohci_hcd_ep93xx_driver #endif #ifdef CONFIG_SOC_AU1X00 #include "ohci-au1xxx.c" -#define PLATFORM_DRIVER ohci_hcd_au1xxx_driver #endif #ifdef CONFIG_PNX8550 #include "ohci-pnx8550.c" -#define PLATFORM_DRIVER ohci_hcd_pnx8550_driver #endif #ifdef CONFIG_USB_OHCI_HCD_PPC_SOC #include "ohci-ppc-soc.c" -#define PLATFORM_DRIVER ohci_hcd_ppc_soc_driver #endif #ifdef CONFIG_ARCH_AT91 #include "ohci-at91.c" -#define PLATFORM_DRIVER ohci_hcd_at91_driver #endif #ifdef CONFIG_ARCH_PNX4008 #include "ohci-pnx4008.c" -#define PLATFORM_DRIVER usb_hcd_pnx4008_driver #endif - -#ifdef CONFIG_USB_OHCI_HCD_PPC_OF -#include "ohci-ppc-of.c" -#define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver -#endif - -#ifdef CONFIG_PPC_PS3 -#include "ohci-ps3.c" -#define PS3_SYSTEM_BUS_DRIVER ps3_ohci_sb_driver -#endif - -#if !defined(PCI_DRIVER) && \ - !defined(PLATFORM_DRIVER) && \ - !defined(OF_PLATFORM_DRIVER) && \ - !defined(SA1111_DRIVER) && \ - !defined(PS3_SYSTEM_BUS_DRIVER) +#if !(defined(CONFIG_PCI) \ + || defined(CONFIG_SA1111) \ + || defined(CONFIG_ARCH_S3C2410) \ + || defined(CONFIG_ARCH_OMAP) \ + || defined (CONFIG_ARCH_LH7A404) \ + || defined (CONFIG_PXA27x) \ + || defined (CONFIG_ARCH_EP93XX) \ + || defined (CONFIG_SOC_AU1X00) \ + || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ + || defined (CONFIG_ARCH_AT91) \ + || defined (CONFIG_ARCH_PNX4008) \ + ) #error "missing bus glue for ohci-hcd" #endif - -static int __init ohci_hcd_mod_init(void) -{ - int retval = 0; - - if (usb_disabled()) - return -ENODEV; - - printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name); - pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, - sizeof (struct ed), sizeof (struct td)); - -#ifdef PS3_SYSTEM_BUS_DRIVER - retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER); - if (retval < 0) - goto error_ps3; -#endif - -#ifdef PLATFORM_DRIVER - retval = platform_driver_register(&PLATFORM_DRIVER); - if (retval < 0) - goto error_platform; -#endif - -#ifdef OF_PLATFORM_DRIVER - retval = of_register_platform_driver(&OF_PLATFORM_DRIVER); - if (retval < 0) - goto error_of_platform; -#endif - -#ifdef SA1111_DRIVER - retval = sa1111_driver_register(&SA1111_DRIVER); - if (retval < 0) - goto error_sa1111; -#endif - -#ifdef PCI_DRIVER - retval = pci_register_driver(&PCI_DRIVER); - if (retval < 0) - goto error_pci; -#endif - - return retval; - - /* Error path */ -#ifdef PCI_DRIVER - error_pci: -#endif -#ifdef SA1111_DRIVER - sa1111_driver_unregister(&SA1111_DRIVER); - error_sa1111: -#endif -#ifdef OF_PLATFORM_DRIVER - of_unregister_platform_driver(&OF_PLATFORM_DRIVER); - error_of_platform: -#endif -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); - error_platform: -#endif -#ifdef PS3_SYSTEM_BUS_DRIVER - ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); - error_ps3: -#endif - return retval; -} -module_init(ohci_hcd_mod_init); - -static void __exit ohci_hcd_mod_exit(void) -{ -#ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); -#endif -#ifdef SA1111_DRIVER - sa1111_driver_unregister(&SA1111_DRIVER); -#endif -#ifdef OF_PLATFORM_DRIVER - of_unregister_platform_driver(&OF_PLATFORM_DRIVER); -#endif -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); -#endif -#ifdef PS3_SYSTEM_BUS_DRIVER - ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); -#endif -} -module_exit(ohci_hcd_mod_exit); - diff --git a/trunk/drivers/usb/host/ohci-lh7a404.c b/trunk/drivers/usb/host/ohci-lh7a404.c index 4a043abd85ea..e9807cf73a2f 100644 --- a/trunk/drivers/usb/host/ohci-lh7a404.c +++ b/trunk/drivers/usb/host/ohci-lh7a404.c @@ -251,3 +251,19 @@ static struct platform_driver ohci_hcd_lh7a404_driver = { }, }; +static int __init ohci_hcd_lh7a404_init (void) +{ + pr_debug (DRIVER_INFO " (LH7A404)"); + pr_debug ("block sizes: ed %d td %d\n", + sizeof (struct ed), sizeof (struct td)); + + return platform_driver_register(&ohci_hcd_lh7a404_driver); +} + +static void __exit ohci_hcd_lh7a404_cleanup (void) +{ + platform_driver_unregister(&ohci_hcd_lh7a404_driver); +} + +module_init (ohci_hcd_lh7a404_init); +module_exit (ohci_hcd_lh7a404_cleanup); diff --git a/trunk/drivers/usb/host/ohci-omap.c b/trunk/drivers/usb/host/ohci-omap.c index 5cfa3d1c4413..27be1f936885 100644 --- a/trunk/drivers/usb/host/ohci-omap.c +++ b/trunk/drivers/usb/host/ohci-omap.c @@ -544,3 +544,22 @@ static struct platform_driver ohci_hcd_omap_driver = { }, }; +static int __init ohci_hcd_omap_init (void) +{ + printk (KERN_DEBUG "%s: " DRIVER_INFO " (OMAP)\n", hcd_name); + if (usb_disabled()) + return -ENODEV; + + pr_debug("%s: block sizes: ed %Zd td %Zd\n", hcd_name, + sizeof (struct ed), sizeof (struct td)); + + return platform_driver_register(&ohci_hcd_omap_driver); +} + +static void __exit ohci_hcd_omap_cleanup (void) +{ + platform_driver_unregister(&ohci_hcd_omap_driver); +} + +module_init (ohci_hcd_omap_init); +module_exit (ohci_hcd_omap_cleanup); diff --git a/trunk/drivers/usb/host/ohci-pci.c b/trunk/drivers/usb/host/ohci-pci.c index b331ac4d0d62..596e0b41e606 100644 --- a/trunk/drivers/usb/host/ohci-pci.c +++ b/trunk/drivers/usb/host/ohci-pci.c @@ -20,154 +20,79 @@ /*-------------------------------------------------------------------------*/ -/* AMD 756, for most chips (early revs), corrupts register - * values on read ... so enable the vendor workaround. - */ -static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd) +static int +ohci_pci_reset (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - ohci->flags = OHCI_QUIRK_AMD756; - ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); - - /* also erratum 10 (suspend/resume issues) */ - device_init_wakeup(&hcd->self.root_hub->dev, 0); - - return 0; + ohci_hcd_init (ohci); + return ohci_init (ohci); } -/* Apple's OHCI driver has a lot of bizarre workarounds - * for this chip. Evidently control and bulk lists - * can get confused. (B&W G3 models, and ...) - */ -static int __devinit ohci_quirk_opti(struct usb_hcd *hcd) +static int __devinit +ohci_pci_start (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; - ohci_dbg (ohci, "WARNING: OPTi workarounds unavailable\n"); - - return 0; -} - -/* Check for NSC87560. We have to look at the bridge (fn1) to - * identify the USB (fn2). This quirk might apply to more or - * even all NSC stuff. - */ -static int __devinit ohci_quirk_ns(struct usb_hcd *hcd) -{ - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - struct pci_dev *b; - - b = pci_get_slot (pdev->bus, PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); - if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO - && b->vendor == PCI_VENDOR_ID_NS) { - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - - ohci->flags |= OHCI_QUIRK_SUPERIO; - ohci_dbg (ohci, "Using NSC SuperIO setup\n"); - } - pci_dev_put(b); - - return 0; -} - -/* Check for Compaq's ZFMicro chipset, which needs short - * delays before control or bulk queues get re-activated - * in finish_unlinks() - */ -static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - - ohci->flags |= OHCI_QUIRK_ZFMICRO; - ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n"); - - return 0; -} - -/* Check for Toshiba SCC OHCI which has big endian registers - * and little endian in memory data structures - */ -static int __devinit ohci_quirk_toshiba_scc(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - - /* That chip is only present in the southbridge of some - * cell based platforms which are supposed to select - * CONFIG_USB_OHCI_BIG_ENDIAN_MMIO. We verify here if - * that was the case though. - */ -#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO - ohci->flags |= OHCI_QUIRK_BE_MMIO; - ohci_dbg (ohci, "enabled big endian Toshiba quirk\n"); - return 0; -#else - ohci_err (ohci, "unsupported big endian Toshiba quirk\n"); - return -ENXIO; -#endif -} - -/* List of quirks for OHCI */ -static const struct pci_device_id ohci_pci_quirks[] = { - { - PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x740c), - .driver_data = (unsigned long)ohci_quirk_amd756, - }, - { - PCI_DEVICE(PCI_VENDOR_ID_OPTI, 0xc861), - .driver_data = (unsigned long)ohci_quirk_opti, - }, - { - PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_ANY_ID), - .driver_data = (unsigned long)ohci_quirk_ns, - }, - { - PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8), - .driver_data = (unsigned long)ohci_quirk_zfmicro, - }, - { - PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, 0x01b6), - .driver_data = (unsigned long)ohci_quirk_toshiba_scc, - }, - /* FIXME for some of the early AMD 760 southbridges, OHCI - * won't work at all. blacklist them. + /* REVISIT this whole block should move to reset(), which handles + * all the other one-time init. */ - - {}, -}; - -static int ohci_pci_reset (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret = 0; - if (hcd->self.controller) { struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - const struct pci_device_id *quirk_id; - quirk_id = pci_match_id(ohci_pci_quirks, pdev); - if (quirk_id != NULL) { - int (*quirk)(struct usb_hcd *ohci); - quirk = (void *)quirk_id->driver_data; - ret = quirk(hcd); + /* AMD 756, for most chips (early revs), corrupts register + * values on read ... so enable the vendor workaround. + */ + if (pdev->vendor == PCI_VENDOR_ID_AMD + && pdev->device == 0x740c) { + ohci->flags = OHCI_QUIRK_AMD756; + ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); + /* also erratum 10 (suspend/resume issues) */ + device_init_wakeup(&hcd->self.root_hub->dev, 0); } - } - if (ret == 0) { - ohci_hcd_init (ohci); - return ohci_init (ohci); - } - return ret; -} + /* FIXME for some of the early AMD 760 southbridges, OHCI + * won't work at all. blacklist them. + */ -static int __devinit ohci_pci_start (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; + /* Apple's OHCI driver has a lot of bizarre workarounds + * for this chip. Evidently control and bulk lists + * can get confused. (B&W G3 models, and ...) + */ + else if (pdev->vendor == PCI_VENDOR_ID_OPTI + && pdev->device == 0xc861) { + ohci_dbg (ohci, + "WARNING: OPTi workarounds unavailable\n"); + } -#ifdef CONFIG_PM /* avoid warnings about unused pdev */ - if (hcd->self.controller) { - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + /* Check for NSC87560. We have to look at the bridge (fn1) to + * identify the USB (fn2). This quirk might apply to more or + * even all NSC stuff. + */ + else if (pdev->vendor == PCI_VENDOR_ID_NS) { + struct pci_dev *b; + + b = pci_get_slot (pdev->bus, + PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); + if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO + && b->vendor == PCI_VENDOR_ID_NS) { + ohci->flags |= OHCI_QUIRK_SUPERIO; + ohci_dbg (ohci, "Using NSC SuperIO setup\n"); + } + pci_dev_put(b); + } + + /* Check for Compaq's ZFMicro chipset, which needs short + * delays before control or bulk queues get re-activated + * in finish_unlinks() + */ + else if (pdev->vendor == PCI_VENDOR_ID_COMPAQ + && pdev->device == 0xa0f8) { + ohci->flags |= OHCI_QUIRK_ZFMICRO; + ohci_dbg (ohci, + "enabled Compaq ZFMicro chipset quirk\n"); + } /* RWC may not be set for add-in PCI cards, since boot * firmware probably ignored them. This transfers PCI @@ -176,14 +101,16 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd) if (device_may_wakeup(&pdev->dev)) ohci->hc_control |= OHCI_CTRL_RWC; } -#endif /* CONFIG_PM */ - ret = ohci_run (ohci); - if (ret < 0) { + /* NOTE: there may have already been a first reset, to + * keep bios/smm irqs from making trouble + */ + if ((ret = ohci_run (ohci)) < 0) { ohci_err (ohci, "can't start\n"); ohci_stop (hcd); + return ret; } - return ret; + return 0; } #ifdef CONFIG_PM @@ -311,3 +238,23 @@ static struct pci_driver ohci_pci_driver = { .shutdown = usb_hcd_pci_shutdown, }; + +static int __init ohci_hcd_pci_init (void) +{ + printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name); + if (usb_disabled()) + return -ENODEV; + + pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, + sizeof (struct ed), sizeof (struct td)); + return pci_register_driver (&ohci_pci_driver); +} +module_init (ohci_hcd_pci_init); + +/*-------------------------------------------------------------------------*/ + +static void __exit ohci_hcd_pci_cleanup (void) +{ + pci_unregister_driver (&ohci_pci_driver); +} +module_exit (ohci_hcd_pci_cleanup); diff --git a/trunk/drivers/usb/host/ohci-pnx4008.c b/trunk/drivers/usb/host/ohci-pnx4008.c index 893b172384da..3a8cbfb69054 100644 --- a/trunk/drivers/usb/host/ohci-pnx4008.c +++ b/trunk/drivers/usb/host/ohci-pnx4008.c @@ -465,3 +465,15 @@ static struct platform_driver usb_hcd_pnx4008_driver = { .remove = usb_hcd_pnx4008_remove, }; +static int __init usb_hcd_pnx4008_init(void) +{ + return platform_driver_register(&usb_hcd_pnx4008_driver); +} + +static void __exit usb_hcd_pnx4008_cleanup(void) +{ + return platform_driver_unregister(&usb_hcd_pnx4008_driver); +} + +module_init(usb_hcd_pnx4008_init); +module_exit(usb_hcd_pnx4008_cleanup); diff --git a/trunk/drivers/usb/host/ohci-pnx8550.c b/trunk/drivers/usb/host/ohci-pnx8550.c index de45eb0051a7..6922b91b1704 100644 --- a/trunk/drivers/usb/host/ohci-pnx8550.c +++ b/trunk/drivers/usb/host/ohci-pnx8550.c @@ -240,3 +240,19 @@ static struct platform_driver ohci_hcd_pnx8550_driver = { .remove = ohci_hcd_pnx8550_drv_remove, }; +static int __init ohci_hcd_pnx8550_init (void) +{ + pr_debug (DRIVER_INFO " (pnx8550)"); + pr_debug ("block sizes: ed %d td %d\n", + sizeof (struct ed), sizeof (struct td)); + + return platform_driver_register(&ohci_hcd_pnx8550_driver); +} + +static void __exit ohci_hcd_pnx8550_cleanup (void) +{ + platform_driver_unregister(&ohci_hcd_pnx8550_driver); +} + +module_init (ohci_hcd_pnx8550_init); +module_exit (ohci_hcd_pnx8550_cleanup); diff --git a/trunk/drivers/usb/host/ohci-ppc-of.c b/trunk/drivers/usb/host/ohci-ppc-of.c deleted file mode 100644 index 08e237c7bc43..000000000000 --- a/trunk/drivers/usb/host/ohci-ppc-of.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * (C) Copyright 2002 Hewlett-Packard Company - * (C) Copyright 2006 Sylvain Munaut - * - * Bus glue for OHCI HC on the of_platform bus - * - * Modified for of_platform bus from ohci-sa1111.c - * - * This file is licenced under the GPL. - */ - -#include - -#include -#include - - -static int __devinit -ohci_ppc_of_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - if ((ret = ohci_init(ohci)) < 0) - return ret; - - if ((ret = ohci_run(ohci)) < 0) { - err("can't start %s", ohci_to_hcd(ohci)->self.bus_name); - ohci_stop(hcd); - return ret; - } - - return 0; -} - -static const struct hc_driver ohci_ppc_of_hc_driver = { - .description = hcd_name, - .product_desc = "OF OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .start = ohci_ppc_of_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - - -static int __devinit -ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) -{ - struct device_node *dn = op->node; - struct usb_hcd *hcd; - struct ohci_hcd *ohci; - struct resource res; - int irq; - - int rv; - int is_bigendian; - - if (usb_disabled()) - return -ENODEV; - - is_bigendian = - device_is_compatible(dn, "ohci-bigendian") || - device_is_compatible(dn, "ohci-be"); - - dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n"); - - rv = of_address_to_resource(dn, 0, &res); - if (rv) - return rv; - - hcd = usb_create_hcd(&ohci_ppc_of_hc_driver, &op->dev, "PPC-OF USB"); - if (!hcd) - return -ENOMEM; - - hcd->rsrc_start = res.start; - hcd->rsrc_len = res.end - res.start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - printk(KERN_ERR __FILE__ ": request_mem_region failed\n"); - rv = -EBUSY; - goto err_rmr; - } - - irq = irq_of_parse_and_map(dn, 0); - if (irq == NO_IRQ) { - printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n"); - rv = -EBUSY; - goto err_irq; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - printk(KERN_ERR __FILE__ ": ioremap failed\n"); - rv = -ENOMEM; - goto err_ioremap; - } - - ohci = hcd_to_ohci(hcd); - if (is_bigendian) - ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; - - ohci_hcd_init(ohci); - - rv = usb_add_hcd(hcd, irq, 0); - if (rv == 0) - return 0; - - iounmap(hcd->regs); -err_ioremap: - irq_dispose_mapping(irq); -err_irq: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_rmr: - usb_put_hcd(hcd); - - return rv; -} - -static int ohci_hcd_ppc_of_remove(struct of_device *op) -{ - struct usb_hcd *hcd = dev_get_drvdata(&op->dev); - dev_set_drvdata(&op->dev, NULL); - - dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); - - usb_remove_hcd(hcd); - - iounmap(hcd->regs); - irq_dispose_mapping(hcd->irq); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - - usb_put_hcd(hcd); - - return 0; -} - -static int ohci_hcd_ppc_of_shutdown(struct of_device *op) -{ - struct usb_hcd *hcd = dev_get_drvdata(&op->dev); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); - - return 0; -} - - -static struct of_device_id ohci_hcd_ppc_of_match[] = { -#ifdef CONFIG_USB_OHCI_HCD_PPC_OF_BE - { - .name = "usb", - .compatible = "ohci-bigendian", - }, - { - .name = "usb", - .compatible = "ohci-be", - }, -#endif -#ifdef CONFIG_USB_OHCI_HCD_PPC_OF_LE - { - .name = "usb", - .compatible = "ohci-littledian", - }, - { - .name = "usb", - .compatible = "ohci-le", - }, -#endif - {}, -}; -MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match); - -#if !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \ - !defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE) -#error "No endianess selected for ppc-of-ohci" -#endif - - -static struct of_platform_driver ohci_hcd_ppc_of_driver = { - .name = "ppc-of-ohci", - .match_table = ohci_hcd_ppc_of_match, - .probe = ohci_hcd_ppc_of_probe, - .remove = ohci_hcd_ppc_of_remove, - .shutdown = ohci_hcd_ppc_of_shutdown, -#ifdef CONFIG_PM - /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ - /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ -#endif - .driver = { - .name = "ppc-of-ohci", - .owner = THIS_MODULE, - }, -}; - diff --git a/trunk/drivers/usb/host/ohci-ppc-soc.c b/trunk/drivers/usb/host/ohci-ppc-soc.c index 1a2e1777ca61..e1a7eb817313 100644 --- a/trunk/drivers/usb/host/ohci-ppc-soc.c +++ b/trunk/drivers/usb/host/ohci-ppc-soc.c @@ -72,7 +72,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, } ohci = hcd_to_ohci(hcd); - ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; + ohci->flags |= OHCI_BIG_ENDIAN; ohci_hcd_init(ohci); retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); @@ -208,3 +208,19 @@ static struct platform_driver ohci_hcd_ppc_soc_driver = { }, }; +static int __init ohci_hcd_ppc_soc_init(void) +{ + pr_debug(DRIVER_INFO " (PPC SOC)\n"); + pr_debug("block sizes: ed %d td %d\n", sizeof(struct ed), + sizeof(struct td)); + + return platform_driver_register(&ohci_hcd_ppc_soc_driver); +} + +static void __exit ohci_hcd_ppc_soc_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_ppc_soc_driver); +} + +module_init(ohci_hcd_ppc_soc_init); +module_exit(ohci_hcd_ppc_soc_cleanup); diff --git a/trunk/drivers/usb/host/ohci-ps3.c b/trunk/drivers/usb/host/ohci-ps3.c deleted file mode 100644 index 69d948b4a701..000000000000 --- a/trunk/drivers/usb/host/ohci-ps3.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * PS3 OHCI Host Controller driver - * - * Copyright (C) 2006 Sony Computer Entertainment Inc. - * Copyright 2006 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 - -static int ps3_ohci_hc_reset(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - - ohci->flags |= OHCI_QUIRK_BE_MMIO; - ohci_hcd_init(ohci); - return ohci_init(ohci); -} - -static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd) -{ - int result; - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - - /* Handle root hub init quirk in spider south bridge. */ - /* Also set PwrOn2PwrGood to 0x7f (254ms). */ - - ohci_writel(ohci, 0x7f000000 | RH_A_PSM | RH_A_OCPM, - &ohci->regs->roothub.a); - ohci_writel(ohci, 0x00060000, &ohci->regs->roothub.b); - - result = ohci_run(ohci); - - if (result < 0) { - err("can't start %s", hcd->self.bus_name); - ohci_stop(hcd); - } - - return result; -} - -static const struct hc_driver ps3_ohci_hc_driver = { - .description = hcd_name, - .product_desc = "PS3 OHCI Host Controller", - .hcd_priv_size = sizeof(struct ohci_hcd), - .irq = ohci_irq, - .flags = HCD_MEMORY | HCD_USB11, - .reset = ps3_ohci_hc_reset, - .start = ps3_ohci_hc_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - .get_frame_number = ohci_get_frame, - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, - .start_port_reset = ohci_start_port_reset, -#if defined(CONFIG_PM) - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif -}; - -/* redefine dev_dbg to do a syntax check */ - -#if !defined(DEBUG) -#undef dev_dbg -static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg( - const struct device *_dev, const char *fmt, ...) {return 0;} -#endif - -static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev) -{ - int result; - struct usb_hcd *hcd; - unsigned int virq; - static u64 dummy_mask = DMA_32BIT_MASK; - - if (usb_disabled()) { - result = -ENODEV; - goto fail_start; - } - - result = ps3_mmio_region_create(dev->m_region); - - if (result) { - dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", - __func__, __LINE__); - result = -EPERM; - goto fail_mmio; - } - - 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); - - if (result) { - dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n", - __func__, __LINE__, virq); - result = -EPERM; - goto fail_irq; - } - - dev->core.power.power_state = PMSG_ON; - dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */ - - hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id); - - if (!hcd) { - dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__, - __LINE__); - result = -ENOMEM; - goto fail_create_hcd; - } - - hcd->rsrc_start = dev->m_region->lpar_addr; - hcd->rsrc_len = dev->m_region->len; - hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); - - if (!hcd->regs) { - dev_dbg(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - result = -EPERM; - goto fail_ioremap; - } - - dev_dbg(&dev->core, "%s:%d: hcd->rsrc_start %lxh\n", __func__, __LINE__, - (unsigned long)hcd->rsrc_start); - dev_dbg(&dev->core, "%s:%d: hcd->rsrc_len %lxh\n", __func__, __LINE__, - (unsigned long)hcd->rsrc_len); - dev_dbg(&dev->core, "%s:%d: hcd->regs %lxh\n", __func__, __LINE__, - (unsigned long)hcd->regs); - dev_dbg(&dev->core, "%s:%d: virq %lu\n", __func__, __LINE__, - (unsigned long)virq); - - ps3_system_bus_set_driver_data(dev, hcd); - - result = usb_add_hcd(hcd, virq, IRQF_DISABLED); - - if (result) { - dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", - __func__, __LINE__, result); - goto fail_add_hcd; - } - - return result; - -fail_add_hcd: - iounmap(hcd->regs); -fail_ioremap: - usb_put_hcd(hcd); -fail_create_hcd: - ps3_free_io_irq(virq); -fail_irq: - ps3_free_mmio_region(dev->m_region); -fail_mmio: -fail_start: - return result; -} - -static int ps3_ohci_sb_remove (struct ps3_system_bus_device *dev) -{ - struct usb_hcd *hcd = - (struct usb_hcd *)ps3_system_bus_get_driver_data(dev); - - usb_put_hcd(hcd); - ps3_system_bus_set_driver_data(dev, NULL); - - return 0; -} - -MODULE_ALIAS("ps3-ohci"); - -static struct ps3_system_bus_driver ps3_ohci_sb_driver = { - .match_id = PS3_MATCH_ID_OHCI, - .core = { - .name = "ps3-ohci-driver", - }, - .probe = ps3_ohci_sb_probe, - .remove = ps3_ohci_sb_remove, -}; diff --git a/trunk/drivers/usb/host/ohci-pxa27x.c b/trunk/drivers/usb/host/ohci-pxa27x.c index f1563dc319d3..3bbea844a9e3 100644 --- a/trunk/drivers/usb/host/ohci-pxa27x.c +++ b/trunk/drivers/usb/host/ohci-pxa27x.c @@ -369,3 +369,19 @@ static struct platform_driver ohci_hcd_pxa27x_driver = { }, }; +static int __init ohci_hcd_pxa27x_init (void) +{ + pr_debug (DRIVER_INFO " (pxa27x)"); + pr_debug ("block sizes: ed %d td %d\n", + sizeof (struct ed), sizeof (struct td)); + + return platform_driver_register(&ohci_hcd_pxa27x_driver); +} + +static void __exit ohci_hcd_pxa27x_cleanup (void) +{ + platform_driver_unregister(&ohci_hcd_pxa27x_driver); +} + +module_init (ohci_hcd_pxa27x_init); +module_exit (ohci_hcd_pxa27x_cleanup); diff --git a/trunk/drivers/usb/host/ohci-s3c2410.c b/trunk/drivers/usb/host/ohci-s3c2410.c index 6829814b7aaf..b350d45033e7 100644 --- a/trunk/drivers/usb/host/ohci-s3c2410.c +++ b/trunk/drivers/usb/host/ohci-s3c2410.c @@ -501,3 +501,15 @@ static struct platform_driver ohci_hcd_s3c2410_driver = { }, }; +static int __init ohci_hcd_s3c2410_init (void) +{ + return platform_driver_register(&ohci_hcd_s3c2410_driver); +} + +static void __exit ohci_hcd_s3c2410_cleanup (void) +{ + platform_driver_unregister(&ohci_hcd_s3c2410_driver); +} + +module_init (ohci_hcd_s3c2410_init); +module_exit (ohci_hcd_s3c2410_cleanup); diff --git a/trunk/drivers/usb/host/ohci-sa1111.c b/trunk/drivers/usb/host/ohci-sa1111.c index 0f48f2d99226..fe0090e33675 100644 --- a/trunk/drivers/usb/host/ohci-sa1111.c +++ b/trunk/drivers/usb/host/ohci-sa1111.c @@ -269,3 +269,19 @@ static struct sa1111_driver ohci_hcd_sa1111_driver = { .remove = ohci_hcd_sa1111_drv_remove, }; +static int __init ohci_hcd_sa1111_init (void) +{ + dbg (DRIVER_INFO " (SA-1111)"); + dbg ("block sizes: ed %d td %d", + sizeof (struct ed), sizeof (struct td)); + + return sa1111_driver_register(&ohci_hcd_sa1111_driver); +} + +static void __exit ohci_hcd_sa1111_cleanup (void) +{ + sa1111_driver_unregister(&ohci_hcd_sa1111_driver); +} + +module_init (ohci_hcd_sa1111_init); +module_exit (ohci_hcd_sa1111_cleanup); diff --git a/trunk/drivers/usb/host/ohci.h b/trunk/drivers/usb/host/ohci.h index 0dafcda37291..405257f3e853 100644 --- a/trunk/drivers/usb/host/ohci.h +++ b/trunk/drivers/usb/host/ohci.h @@ -394,9 +394,8 @@ struct ohci_hcd { #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ #define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ #define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */ -#define OHCI_QUIRK_BE_DESC 0x08 /* BE descriptors */ -#define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */ -#define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ +#define OHCI_BIG_ENDIAN 0x08 /* big endian HC */ +#define OHCI_QUIRK_ZFMICRO 0x10 /* Compaq ZFMicro chipset*/ // there are also chip quirks/bugs in init logic }; @@ -440,164 +439,117 @@ static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci) * a minority (notably the IBM STB04XXX and the Motorola MPC5200 * processors) implement them in big endian format. * - * In addition some more exotic implementations like the Toshiba - * Spider (aka SCC) cell southbridge are "mixed" endian, that is, - * they have a different endianness for registers vs. in-memory - * descriptors. - * * This attempts to support either format at compile time without a * runtime penalty, or both formats with the additional overhead * of checking a flag bit. - * - * That leads to some tricky Kconfig rules howevber. There are - * different defaults based on some arch/ppc platforms, though - * the basic rules are: - * - * Controller type Kconfig options needed - * --------------- ---------------------- - * little endian CONFIG_USB_OHCI_LITTLE_ENDIAN - * - * fully big endian CONFIG_USB_OHCI_BIG_ENDIAN_DESC _and_ - * CONFIG_USB_OHCI_BIG_ENDIAN_MMIO - * - * mixed endian CONFIG_USB_OHCI_LITTLE_ENDIAN _and_ - * CONFIG_USB_OHCI_BIG_ENDIAN_{MMIO,DESC} - * - * (If you have a mixed endian controller, you -must- also define - * CONFIG_USB_OHCI_LITTLE_ENDIAN or things will not work when building - * both your mixed endian and a fully big endian controller support in - * the same kernel image). */ -#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_DESC -#ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN -#define big_endian_desc(ohci) (ohci->flags & OHCI_QUIRK_BE_DESC) -#else -#define big_endian_desc(ohci) 1 /* only big endian */ -#endif -#else -#define big_endian_desc(ohci) 0 /* only little endian */ -#endif +#ifdef CONFIG_USB_OHCI_BIG_ENDIAN -#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO #ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN -#define big_endian_mmio(ohci) (ohci->flags & OHCI_QUIRK_BE_MMIO) +#define big_endian(ohci) (ohci->flags & OHCI_BIG_ENDIAN) /* either */ #else -#define big_endian_mmio(ohci) 1 /* only big endian */ -#endif -#else -#define big_endian_mmio(ohci) 0 /* only little endian */ +#define big_endian(ohci) 1 /* only big endian */ #endif /* * Big-endian read/write functions are arch-specific. * Other arches can be added if/when they're needed. - * - * REVISIT: arch/powerpc now has readl/writel_be, so the - * definition below can die once the STB04xxx support is - * finally ported over. */ -#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE) +#if defined(CONFIG_PPC) #define readl_be(addr) in_be32((__force unsigned *)addr) #define writel_be(val, addr) out_be32((__force unsigned *)addr, val) #endif -static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci, - __hc32 __iomem * regs) +static inline unsigned int ohci_readl (const struct ohci_hcd *ohci, + __hc32 __iomem * regs) { -#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO - return big_endian_mmio(ohci) ? - readl_be ((__force u32 *)regs) : - readl ((__force u32 *)regs); -#else - return readl ((__force u32 *)regs); -#endif + return big_endian(ohci) ? readl_be (regs) : readl ((__force u32 *)regs); } -static inline void _ohci_writel (const struct ohci_hcd *ohci, - const unsigned int val, __hc32 __iomem *regs) +static inline void ohci_writel (const struct ohci_hcd *ohci, + const unsigned int val, __hc32 __iomem *regs) { -#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO - big_endian_mmio(ohci) ? - writel_be (val, (__force u32 *)regs) : - writel (val, (__force u32 *)regs); -#else - writel (val, (__force u32 *)regs); -#endif + big_endian(ohci) ? writel_be (val, regs) : + writel (val, (__force u32 *)regs); } +#else /* !CONFIG_USB_OHCI_BIG_ENDIAN */ + +#define big_endian(ohci) 0 /* only little endian */ + #ifdef CONFIG_ARCH_LH7A404 -/* Marc Singer: at the time this code was written, the LH7A404 - * had a problem reading the USB host registers. This - * implementation of the ohci_readl function performs the read - * twice as a work-around. - */ -#define ohci_readl(o,r) (_ohci_readl(o,r),_ohci_readl(o,r)) -#define ohci_writel(o,v,r) _ohci_writel(o,v,r) + /* Marc Singer: at the time this code was written, the LH7A404 + * had a problem reading the USB host registers. This + * implementation of the ohci_readl function performs the read + * twice as a work-around. + */ +static inline unsigned int +ohci_readl (const struct ohci_hcd *ohci, const __hc32 *regs) +{ + *(volatile __force unsigned int*) regs; + return *(volatile __force unsigned int*) regs; +} #else -#define ohci_readl(o,r) _ohci_readl(o,r) -#define ohci_writel(o,v,r) _ohci_writel(o,v,r) + /* Standard version of ohci_readl uses standard, platform + * specific implementation. */ +static inline unsigned int +ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs) +{ + return readl(regs); +} #endif +static inline void ohci_writel (const struct ohci_hcd *ohci, + const unsigned int val, __hc32 __iomem *regs) +{ + writel (val, regs); +} + +#endif /* !CONFIG_USB_OHCI_BIG_ENDIAN */ /*-------------------------------------------------------------------------*/ /* cpu to ohci */ static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x) { - return big_endian_desc(ohci) ? - (__force __hc16)cpu_to_be16(x) : - (__force __hc16)cpu_to_le16(x); + return big_endian(ohci) ? (__force __hc16)cpu_to_be16(x) : (__force __hc16)cpu_to_le16(x); } static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x) { - return big_endian_desc(ohci) ? - cpu_to_be16p(x) : - cpu_to_le16p(x); + return big_endian(ohci) ? cpu_to_be16p(x) : cpu_to_le16p(x); } static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x) { - return big_endian_desc(ohci) ? - (__force __hc32)cpu_to_be32(x) : - (__force __hc32)cpu_to_le32(x); + return big_endian(ohci) ? (__force __hc32)cpu_to_be32(x) : (__force __hc32)cpu_to_le32(x); } static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x) { - return big_endian_desc(ohci) ? - cpu_to_be32p(x) : - cpu_to_le32p(x); + return big_endian(ohci) ? cpu_to_be32p(x) : cpu_to_le32p(x); } /* ohci to cpu */ static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x) { - return big_endian_desc(ohci) ? - be16_to_cpu((__force __be16)x) : - le16_to_cpu((__force __le16)x); + return big_endian(ohci) ? be16_to_cpu((__force __be16)x) : le16_to_cpu((__force __le16)x); } static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x) { - return big_endian_desc(ohci) ? - be16_to_cpup((__force __be16 *)x) : - le16_to_cpup((__force __le16 *)x); + return big_endian(ohci) ? be16_to_cpup((__force __be16 *)x) : le16_to_cpup((__force __le16 *)x); } static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x) { - return big_endian_desc(ohci) ? - be32_to_cpu((__force __be32)x) : - le32_to_cpu((__force __le32)x); + return big_endian(ohci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x); } static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) { - return big_endian_desc(ohci) ? - be32_to_cpup((__force __be32 *)x) : - le32_to_cpup((__force __le32 *)x); + return big_endian(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x); } /*-------------------------------------------------------------------------*/ @@ -605,9 +557,6 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) /* HCCA frame number is 16 bits, but is accessed as 32 bits since not all * hardware handles 16 bit reads. That creates a different confusion on * some big-endian SOC implementations. Same thing happens with PSW access. - * - * FIXME: Deal with that as a runtime quirk when STB03xxx is ported over - * to arch/powerpc */ #ifdef CONFIG_STB03xxx @@ -619,7 +568,7 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) static inline u16 ohci_frame_no(const struct ohci_hcd *ohci) { u32 tmp; - if (big_endian_desc(ohci)) { + if (big_endian(ohci)) { tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no); tmp >>= OHCI_BE_FRAME_NO_SHIFT; } else @@ -631,7 +580,7 @@ static inline u16 ohci_frame_no(const struct ohci_hcd *ohci) static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci, const struct td *td, int index) { - return (__hc16 *)(big_endian_desc(ohci) ? + return (__hc16 *)(big_endian(ohci) ? &td->hwPSW[index ^ 1] : &td->hwPSW[index]); } diff --git a/trunk/drivers/usb/host/uhci-debug.c b/trunk/drivers/usb/host/uhci-debug.c index 5d6c06bc4524..e345f15b7d87 100644 --- a/trunk/drivers/usb/host/uhci-debug.c +++ b/trunk/drivers/usb/host/uhci-debug.c @@ -168,13 +168,9 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) space, "", qh, qtype, le32_to_cpu(qh->link), le32_to_cpu(element)); if (qh->type == USB_ENDPOINT_XFER_ISOC) - out += sprintf(out, "%*s period %d phase %d load %d us, " - "frame %x desc [%p]\n", - space, "", qh->period, qh->phase, qh->load, - qh->iso_frame, qh->iso_packet_desc); - else if (qh->type == USB_ENDPOINT_XFER_INT) - out += sprintf(out, "%*s period %d phase %d load %d us\n", - space, "", qh->period, qh->phase, qh->load); + out += sprintf(out, "%*s period %d frame %x desc [%p]\n", + space, "", qh->period, qh->iso_frame, + qh->iso_packet_desc); if (element & UHCI_PTR_QH) out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); @@ -212,7 +208,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) space, "", nurbs); } - if (qh->dummy_td) { + if (qh->udev) { out += sprintf(out, "%*s Dummy TD\n", space, ""); out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0); } @@ -351,80 +347,31 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) struct uhci_qh *qh; struct uhci_td *td; struct list_head *tmp, *head; - int nframes, nerrs; out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); out += sprintf(out, "HC status\n"); out += uhci_show_status(uhci, out, len - (out - buf)); - - out += sprintf(out, "Periodic load table\n"); - for (i = 0; i < MAX_PHASE; ++i) { - out += sprintf(out, "\t%d", uhci->load[i]); - if (i % 8 == 7) - *out++ = '\n'; - } - out += sprintf(out, "Total: %d, #INT: %d, #ISO: %d\n", - uhci->total_load, - uhci_to_hcd(uhci)->self.bandwidth_int_reqs, - uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs); if (debug <= 1) return out - buf; out += sprintf(out, "Frame List\n"); - nframes = 10; - nerrs = 0; for (i = 0; i < UHCI_NUMFRAMES; ++i) { - __le32 link, qh_dma; - - j = 0; td = uhci->frame_cpu[i]; - link = uhci->frame[i]; if (!td) - goto check_link; + continue; - if (nframes > 0) { - out += sprintf(out, "- Frame %d -> (%08x)\n", - i, le32_to_cpu(link)); - j = 1; - } + out += sprintf(out, "- Frame %d\n", i); \ + if (td->dma_handle != (dma_addr_t)uhci->frame[i]) + out += sprintf(out, " frame list does not match td->dma_handle!\n"); head = &td->fl_list; tmp = head; do { td = list_entry(tmp, struct uhci_td, fl_list); tmp = tmp->next; - if (cpu_to_le32(td->dma_handle) != link) { - if (nframes > 0) - out += sprintf(out, " link does " - "not match list entry!\n"); - else - ++nerrs; - } - if (nframes > 0) - out += uhci_show_td(td, out, - len - (out - buf), 4); - link = td->link; + out += uhci_show_td(td, out, len - (out - buf), 4); } while (tmp != head); - -check_link: - qh_dma = uhci_frame_skel_link(uhci, i); - if (link != qh_dma) { - if (nframes > 0) { - if (!j) { - out += sprintf(out, - "- Frame %d -> (%08x)\n", - i, le32_to_cpu(link)); - j = 1; - } - out += sprintf(out, " link does not match " - "QH (%08x)!\n", le32_to_cpu(qh_dma)); - } else - ++nerrs; - } - nframes -= j; } - if (nerrs > 0) - out += sprintf(out, "Skipped %d bad links\n", nerrs); out += sprintf(out, "Skeleton QHs\n"); diff --git a/trunk/drivers/usb/host/uhci-hcd.c b/trunk/drivers/usb/host/uhci-hcd.c index 49b9d390b95f..e0d4c2358b39 100644 --- a/trunk/drivers/usb/host/uhci-hcd.c +++ b/trunk/drivers/usb/host/uhci-hcd.c @@ -92,34 +92,6 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); static void wakeup_rh(struct uhci_hcd *uhci); static void uhci_get_current_frame_number(struct uhci_hcd *uhci); -/* - * Calculate the link pointer DMA value for the first Skeleton QH in a frame. - */ -static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame) -{ - int skelnum; - - /* - * The interrupt queues will be interleaved as evenly as possible. - * There's not much to be done about period-1 interrupts; they have - * to occur in every frame. But we can schedule period-2 interrupts - * in odd-numbered frames, period-4 interrupts in frames congruent - * to 2 (mod 4), and so on. This way each frame only has two - * interrupt QHs, which will help spread out bandwidth utilization. - * - * ffs (Find First bit Set) does exactly what we need: - * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8], - * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc. - * ffs >= 7 => not on any high-period queue, so use - * skel_int1_qh = skelqh[9]. - * Add in UHCI_NUMFRAMES to insure at least one bit is set. - */ - skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES); - if (skelnum <= 1) - skelnum = 9; - return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle); -} - #include "uhci-debug.c" #include "uhci-q.c" #include "uhci-hub.c" @@ -659,11 +631,32 @@ static int uhci_start(struct usb_hcd *hcd) /* * Fill the frame list: make all entries point to the proper * interrupt queue. + * + * The interrupt queues will be interleaved as evenly as possible. + * There's not much to be done about period-1 interrupts; they have + * to occur in every frame. But we can schedule period-2 interrupts + * in odd-numbered frames, period-4 interrupts in frames congruent + * to 2 (mod 4), and so on. This way each frame only has two + * interrupt QHs, which will help spread out bandwidth utilization. */ for (i = 0; i < UHCI_NUMFRAMES; i++) { + int irq; + + /* + * ffs (Find First bit Set) does exactly what we need: + * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8], + * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc. + * ffs >= 7 => not on any high-period queue, so use + * skel_int1_qh = skelqh[9]. + * Add UHCI_NUMFRAMES to insure at least one bit is set. + */ + irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES); + if (irq <= 1) + irq = 9; /* Only place we don't use the frame list routines */ - uhci->frame[i] = uhci_frame_skel_link(uhci, i); + uhci->frame[i] = UHCI_PTR_QH | + cpu_to_le32(uhci->skelqh[irq]->dma_handle); } /* diff --git a/trunk/drivers/usb/host/uhci-hcd.h b/trunk/drivers/usb/host/uhci-hcd.h index 74469b5bcb61..108e3de2dc26 100644 --- a/trunk/drivers/usb/host/uhci-hcd.h +++ b/trunk/drivers/usb/host/uhci-hcd.h @@ -83,7 +83,6 @@ #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ #define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames * can be scheduled */ -#define MAX_PHASE 32 /* Periodic scheduling length */ /* When no queues need Full-Speed Bandwidth Reclamation, * delay this long before turning FSBR off */ @@ -142,8 +141,6 @@ struct uhci_qh { unsigned long advance_jiffies; /* Time of last queue advance */ unsigned int unlink_frame; /* When the QH was unlinked */ unsigned int period; /* For Interrupt and Isochronous QHs */ - short phase; /* Between 0 and period-1 */ - short load; /* Periodic time requirement, in us */ unsigned int iso_frame; /* Frame # for iso_packet_desc */ int iso_status; /* Status for Isochronous URBs */ @@ -156,8 +153,6 @@ struct uhci_qh { unsigned int needs_fixup:1; /* Must fix the TD toggle values */ unsigned int is_stopped:1; /* Queue was stopped by error/unlink */ unsigned int wait_expired:1; /* QH_WAIT_TIMEOUT has expired */ - unsigned int bandwidth_reserved:1; /* Periodic bandwidth has - * been allocated */ } __attribute__((aligned(16))); /* @@ -419,9 +414,6 @@ struct uhci_hcd { wait_queue_head_t waitqh; /* endpoint_disable waiters */ int num_waiting; /* Number of waiters */ - - int total_load; /* Sum of array values */ - short load[MAX_PHASE]; /* Periodic allocations */ }; /* Convert between a usb_hcd pointer and the corresponding uhci_hcd */ diff --git a/trunk/drivers/usb/host/uhci-q.c b/trunk/drivers/usb/host/uhci-q.c index 2cbb239e63f8..30b88459ac7d 100644 --- a/trunk/drivers/usb/host/uhci-q.c +++ b/trunk/drivers/usb/host/uhci-q.c @@ -248,26 +248,16 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, INIT_LIST_HEAD(&qh->node); if (udev) { /* Normal QH */ - qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - if (qh->type != USB_ENDPOINT_XFER_ISOC) { - qh->dummy_td = uhci_alloc_td(uhci); - if (!qh->dummy_td) { - dma_pool_free(uhci->qh_pool, qh, dma_handle); - return NULL; - } + qh->dummy_td = uhci_alloc_td(uhci); + if (!qh->dummy_td) { + dma_pool_free(uhci->qh_pool, qh, dma_handle); + return NULL; } qh->state = QH_STATE_IDLE; qh->hep = hep; qh->udev = udev; hep->hcpriv = qh; - - if (qh->type == USB_ENDPOINT_XFER_INT || - qh->type == USB_ENDPOINT_XFER_ISOC) - qh->load = usb_calc_bus_time(udev->speed, - usb_endpoint_dir_in(&hep->desc), - qh->type == USB_ENDPOINT_XFER_ISOC, - le16_to_cpu(hep->desc.wMaxPacketSize)) - / 1000 + 1; + qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; } else { /* Skeleton QH */ qh->state = QH_STATE_ACTIVE; @@ -285,8 +275,7 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) list_del(&qh->node); if (qh->udev) { qh->hep->hcpriv = NULL; - if (qh->dummy_td) - uhci_free_td(uhci, qh->dummy_td); + uhci_free_td(uhci, qh->dummy_td); } dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); } @@ -338,7 +327,7 @@ static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh, goto done; qh->element = UHCI_PTR_TERM; - /* Control pipes don't have to worry about toggles */ + /* Control pipes have to worry about toggles */ if (qh->type == USB_ENDPOINT_XFER_CONTROL) goto done; @@ -504,121 +493,6 @@ static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh) wake_up_all(&uhci->waitqh); } -/* - * Find the highest existing bandwidth load for a given phase and period. - */ -static int uhci_highest_load(struct uhci_hcd *uhci, int phase, int period) -{ - int highest_load = uhci->load[phase]; - - for (phase += period; phase < MAX_PHASE; phase += period) - highest_load = max_t(int, highest_load, uhci->load[phase]); - return highest_load; -} - -/* - * Set qh->phase to the optimal phase for a periodic transfer and - * check whether the bandwidth requirement is acceptable. - */ -static int uhci_check_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh) -{ - int minimax_load; - - /* Find the optimal phase (unless it is already set) and get - * its load value. */ - if (qh->phase >= 0) - minimax_load = uhci_highest_load(uhci, qh->phase, qh->period); - else { - int phase, load; - int max_phase = min_t(int, MAX_PHASE, qh->period); - - qh->phase = 0; - minimax_load = uhci_highest_load(uhci, qh->phase, qh->period); - for (phase = 1; phase < max_phase; ++phase) { - load = uhci_highest_load(uhci, phase, qh->period); - if (load < minimax_load) { - minimax_load = load; - qh->phase = phase; - } - } - } - - /* Maximum allowable periodic bandwidth is 90%, or 900 us per frame */ - if (minimax_load + qh->load > 900) { - dev_dbg(uhci_dev(uhci), "bandwidth allocation failed: " - "period %d, phase %d, %d + %d us\n", - qh->period, qh->phase, minimax_load, qh->load); - return -ENOSPC; - } - return 0; -} - -/* - * Reserve a periodic QH's bandwidth in the schedule - */ -static void uhci_reserve_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh) -{ - int i; - int load = qh->load; - char *p = "??"; - - for (i = qh->phase; i < MAX_PHASE; i += qh->period) { - uhci->load[i] += load; - uhci->total_load += load; - } - uhci_to_hcd(uhci)->self.bandwidth_allocated = - uhci->total_load / MAX_PHASE; - switch (qh->type) { - case USB_ENDPOINT_XFER_INT: - ++uhci_to_hcd(uhci)->self.bandwidth_int_reqs; - p = "INT"; - break; - case USB_ENDPOINT_XFER_ISOC: - ++uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs; - p = "ISO"; - break; - } - qh->bandwidth_reserved = 1; - dev_dbg(uhci_dev(uhci), - "%s dev %d ep%02x-%s, period %d, phase %d, %d us\n", - "reserve", qh->udev->devnum, - qh->hep->desc.bEndpointAddress, p, - qh->period, qh->phase, load); -} - -/* - * Release a periodic QH's bandwidth reservation - */ -static void uhci_release_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh) -{ - int i; - int load = qh->load; - char *p = "??"; - - for (i = qh->phase; i < MAX_PHASE; i += qh->period) { - uhci->load[i] -= load; - uhci->total_load -= load; - } - uhci_to_hcd(uhci)->self.bandwidth_allocated = - uhci->total_load / MAX_PHASE; - switch (qh->type) { - case USB_ENDPOINT_XFER_INT: - --uhci_to_hcd(uhci)->self.bandwidth_int_reqs; - p = "INT"; - break; - case USB_ENDPOINT_XFER_ISOC: - --uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs; - p = "ISO"; - break; - } - qh->bandwidth_reserved = 0; - dev_dbg(uhci_dev(uhci), - "%s dev %d ep%02x-%s, period %d, phase %d, %d us\n", - "release", qh->udev->devnum, - qh->hep->desc.bEndpointAddress, p, - qh->period, qh->phase, load); -} - static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb) { @@ -922,6 +796,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, wmb(); qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); qh->dummy_td = td; + qh->period = urb->interval; usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle); @@ -952,42 +827,28 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct uhci_qh *qh) { - int ret; + int exponent; /* USB 1.1 interrupt transfers only involve one packet per interval. * Drivers can submit URBs of any length, but longer ones will need * multiple intervals to complete. */ - if (!qh->bandwidth_reserved) { - int exponent; + /* Figure out which power-of-two queue to use */ + for (exponent = 7; exponent >= 0; --exponent) { + if ((1 << exponent) <= urb->interval) + break; + } + if (exponent < 0) + return -EINVAL; + urb->interval = 1 << exponent; - /* Figure out which power-of-two queue to use */ - for (exponent = 7; exponent >= 0; --exponent) { - if ((1 << exponent) <= urb->interval) - break; - } - if (exponent < 0) - return -EINVAL; - qh->period = 1 << exponent; + if (qh->period == 0) qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)]; + else if (qh->period != urb->interval) + return -EINVAL; /* Can't change the period */ - /* For now, interrupt phase is fixed by the layout - * of the QH lists. */ - qh->phase = (qh->period / 2) & (MAX_PHASE - 1); - ret = uhci_check_bandwidth(uhci, qh); - if (ret) - return ret; - } else if (qh->period > urb->interval) - return -EINVAL; /* Can't decrease the period */ - - ret = uhci_submit_common(uhci, urb, qh); - if (ret == 0) { - urb->interval = qh->period; - if (!qh->bandwidth_reserved) - uhci_reserve_bandwidth(uhci, qh); - } - return ret; + return uhci_submit_common(uhci, urb, qh); } /* @@ -1134,32 +995,15 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, return -EFBIG; /* Check the period and figure out the starting frame number */ - if (!qh->bandwidth_reserved) { - qh->period = urb->interval; + if (qh->period == 0) { if (urb->transfer_flags & URB_ISO_ASAP) { - qh->phase = -1; /* Find the best phase */ - i = uhci_check_bandwidth(uhci, qh); - if (i) - return i; - - /* Allow a little time to allocate the TDs */ uhci_get_current_frame_number(uhci); - frame = uhci->frame_number + 10; - - /* Move forward to the first frame having the - * correct phase */ - urb->start_frame = frame + ((qh->phase - frame) & - (qh->period - 1)); + urb->start_frame = uhci->frame_number + 10; } else { i = urb->start_frame - uhci->last_iso_frame; if (i <= 0 || i >= UHCI_NUMFRAMES) return -EINVAL; - qh->phase = urb->start_frame & (qh->period - 1); - i = uhci_check_bandwidth(uhci, qh); - if (i) - return i; } - } else if (qh->period != urb->interval) { return -EINVAL; /* Can't change the period */ @@ -1205,6 +1049,9 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, /* Set the interrupt-on-completion flag on the last packet. */ td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); + qh->skel = uhci->skel_iso_qh; + qh->period = urb->interval; + /* Add the TDs to the frame list */ frame = urb->start_frame; list_for_each_entry(td, &urbp->td_list, list) { @@ -1218,9 +1065,6 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, qh->iso_status = 0; } - qh->skel = uhci->skel_iso_qh; - if (!qh->bandwidth_reserved) - uhci_reserve_bandwidth(uhci, qh); return 0; } @@ -1275,6 +1119,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, unsigned long flags; struct urb_priv *urbp; struct uhci_qh *qh; + int bustime; spin_lock_irqsave(&uhci->lock, flags); @@ -1304,11 +1149,35 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, ret = uhci_submit_bulk(uhci, urb, qh); break; case USB_ENDPOINT_XFER_INT: - ret = uhci_submit_interrupt(uhci, urb, qh); + if (list_empty(&qh->queue)) { + bustime = usb_check_bandwidth(urb->dev, urb); + if (bustime < 0) + ret = bustime; + else { + ret = uhci_submit_interrupt(uhci, urb, qh); + if (ret == 0) + usb_claim_bandwidth(urb->dev, urb, bustime, 0); + } + } else { /* inherit from parent */ + struct urb_priv *eurbp; + + eurbp = list_entry(qh->queue.prev, struct urb_priv, + node); + urb->bandwidth = eurbp->urb->bandwidth; + ret = uhci_submit_interrupt(uhci, urb, qh); + } break; case USB_ENDPOINT_XFER_ISOC: urb->error_count = 0; + bustime = usb_check_bandwidth(urb->dev, urb); + if (bustime < 0) { + ret = bustime; + break; + } + ret = uhci_submit_isochronous(uhci, urb, qh); + if (ret == 0) + usb_claim_bandwidth(urb->dev, urb, bustime, 1); break; } if (ret != 0) @@ -1405,6 +1274,24 @@ __acquires(uhci->lock) uhci_free_urb_priv(uhci, urbp); + switch (qh->type) { + case USB_ENDPOINT_XFER_ISOC: + /* Release bandwidth for Interrupt or Isoc. transfers */ + if (urb->bandwidth) + usb_release_bandwidth(urb->dev, urb, 1); + break; + case USB_ENDPOINT_XFER_INT: + /* Release bandwidth for Interrupt or Isoc. transfers */ + /* Make sure we don't release if we have a queued URB */ + if (list_empty(&qh->queue) && urb->bandwidth) + usb_release_bandwidth(urb->dev, urb, 0); + else + /* bandwidth was passed on to queued URB, */ + /* so don't let usb_unlink_urb() release it */ + urb->bandwidth = 0; + break; + } + spin_unlock(&uhci->lock); usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb); spin_lock(&uhci->lock); @@ -1413,8 +1300,9 @@ __acquires(uhci->lock) * reserved bandwidth. */ if (list_empty(&qh->queue)) { uhci_unlink_qh(uhci, qh); - if (qh->bandwidth_reserved) - uhci_release_bandwidth(uhci, qh); + + /* Bandwidth stuff not yet implemented */ + qh->period = 0; } } diff --git a/trunk/drivers/usb/image/mdc800.c b/trunk/drivers/usb/image/mdc800.c index d308afd06935..63a84bbc310d 100644 --- a/trunk/drivers/usb/image/mdc800.c +++ b/trunk/drivers/usb/image/mdc800.c @@ -565,15 +565,11 @@ static void mdc800_usb_disconnect (struct usb_interface *intf) usb_deregister_dev(intf, &mdc800_class); - /* must be under lock to make sure no URB - is submitted after usb_kill_urb() */ - mutex_lock(&mdc800->io_lock); mdc800->state=NOT_CONNECTED; usb_kill_urb(mdc800->irq_urb); usb_kill_urb(mdc800->write_urb); usb_kill_urb(mdc800->download_urb); - mutex_unlock(&mdc800->io_lock); mdc800->dev = NULL; usb_set_intfdata(intf, NULL); diff --git a/trunk/drivers/usb/input/Kconfig b/trunk/drivers/usb/input/Kconfig index 2e71d3cca198..aa6a620c162f 100644 --- a/trunk/drivers/usb/input/Kconfig +++ b/trunk/drivers/usb/input/Kconfig @@ -352,15 +352,3 @@ config USB_APPLETOUCH To compile this driver as a module, choose M here: the module will be called appletouch. - -config USB_GTCO - tristate "GTCO CalComp/InterWrite USB Support" - depends on USB && INPUT - ---help--- - Say Y here if you want to use the USB version of the GTCO - CalComp/InterWrite Tablet. Make sure to say Y to "Mouse support" - (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" - (CONFIG_INPUT_EVDEV) as well. - - To compile this driver as a module, choose M here: the - module will be called gtco. diff --git a/trunk/drivers/usb/input/Makefile b/trunk/drivers/usb/input/Makefile index a9d206c945e9..a06024e5cd56 100644 --- a/trunk/drivers/usb/input/Makefile +++ b/trunk/drivers/usb/input/Makefile @@ -48,7 +48,6 @@ obj-$(CONFIG_USB_ACECAD) += acecad.o obj-$(CONFIG_USB_YEALINK) += yealink.o obj-$(CONFIG_USB_XPAD) += xpad.o obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o -obj-$(CONFIG_USB_GTCO) += gtco.o ifeq ($(CONFIG_USB_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/trunk/drivers/usb/input/gtco.c b/trunk/drivers/usb/input/gtco.c deleted file mode 100644 index 203cdc1bbba4..000000000000 --- a/trunk/drivers/usb/input/gtco.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* -*- linux-c -*- - -GTCO digitizer USB driver - -Use the err(), dbg() and info() macros from usb.h for system logging - -TO CHECK: Is pressure done right on report 5? - -Copyright (C) 2006 GTCO CalComp - -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; version 2 -of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation, and that the name of GTCO-CalComp not be used in advertising -or publicity pertaining to distribution of the software without specific, -written prior permission. GTCO-CalComp makes no representations about the -suitability of this software for any purpose. It is provided "as is" -without express or implied warranty. - -GTCO-CALCOMP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -EVENT SHALL GTCO-CALCOMP BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTIONS, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - -GTCO CalComp, Inc. -7125 Riverwood Drive -Columbia, MD 21046 - -Jeremy Roberson jroberson@gtcocalcomp.com -Scott Hill shill@gtcocalcomp.com -*/ - - - -/*#define DEBUG*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include -#include - -/* Version with a Major number of 2 is for kernel inclusion only. */ -#define GTCO_VERSION "2.00.0006" - - -/* MACROS */ - -#define VENDOR_ID_GTCO 0x078C -#define PID_400 0x400 -#define PID_401 0x401 -#define PID_1000 0x1000 -#define PID_1001 0x1001 -#define PID_1002 0x1002 - -/* Max size of a single report */ -#define REPORT_MAX_SIZE 10 - - -/* Bitmask whether pen is in range */ -#define MASK_INRANGE 0x20 -#define MASK_BUTTON 0x01F - -#define PATHLENGTH 64 - -/* DATA STRUCTURES */ - -/* Device table */ -static struct usb_device_id gtco_usbid_table [] = { - { USB_DEVICE(VENDOR_ID_GTCO, PID_400) }, - { USB_DEVICE(VENDOR_ID_GTCO, PID_401) }, - { USB_DEVICE(VENDOR_ID_GTCO, PID_1000) }, - { USB_DEVICE(VENDOR_ID_GTCO, PID_1001) }, - { USB_DEVICE(VENDOR_ID_GTCO, PID_1002) }, - { } -}; -MODULE_DEVICE_TABLE (usb, gtco_usbid_table); - - -/* Structure to hold all of our device specific stuff */ -struct gtco { - - struct input_dev *inputdevice; /* input device struct pointer */ - struct usb_device *usbdev; /* the usb device for this device */ - struct urb *urbinfo; /* urb for incoming reports */ - dma_addr_t buf_dma; /* dma addr of the data buffer*/ - unsigned char * buffer; /* databuffer for reports */ - - char usbpath[PATHLENGTH]; - int openCount; - - /* Information pulled from Report Descriptor */ - u32 usage; - u32 min_X; - u32 max_X; - u32 min_Y; - u32 max_Y; - s8 mintilt_X; - s8 maxtilt_X; - s8 mintilt_Y; - s8 maxtilt_Y; - u32 maxpressure; - u32 minpressure; -}; - - - -/* Code for parsing the HID REPORT DESCRIPTOR */ - -/* From HID1.11 spec */ -struct hid_descriptor -{ - struct usb_descriptor_header header; - __le16 bcdHID; - u8 bCountryCode; - u8 bNumDescriptors; - u8 bDescriptorType; - __le16 wDescriptorLength; -} __attribute__ ((packed)); - - -#define HID_DESCRIPTOR_SIZE 9 -#define HID_DEVICE_TYPE 33 -#define REPORT_DEVICE_TYPE 34 - - -#define PREF_TAG(x) ((x)>>4) -#define PREF_TYPE(x) ((x>>2)&0x03) -#define PREF_SIZE(x) ((x)&0x03) - -#define TYPE_MAIN 0 -#define TYPE_GLOBAL 1 -#define TYPE_LOCAL 2 -#define TYPE_RESERVED 3 - -#define TAG_MAIN_INPUT 0x8 -#define TAG_MAIN_OUTPUT 0x9 -#define TAG_MAIN_FEATURE 0xB -#define TAG_MAIN_COL_START 0xA -#define TAG_MAIN_COL_END 0xC - -#define TAG_GLOB_USAGE 0 -#define TAG_GLOB_LOG_MIN 1 -#define TAG_GLOB_LOG_MAX 2 -#define TAG_GLOB_PHYS_MIN 3 -#define TAG_GLOB_PHYS_MAX 4 -#define TAG_GLOB_UNIT_EXP 5 -#define TAG_GLOB_UNIT 6 -#define TAG_GLOB_REPORT_SZ 7 -#define TAG_GLOB_REPORT_ID 8 -#define TAG_GLOB_REPORT_CNT 9 -#define TAG_GLOB_PUSH 10 -#define TAG_GLOB_POP 11 - -#define TAG_GLOB_MAX 12 - -#define DIGITIZER_USAGE_TIP_PRESSURE 0x30 -#define DIGITIZER_USAGE_TILT_X 0x3D -#define DIGITIZER_USAGE_TILT_Y 0x3E - - -/* - * - * This is an abbreviated parser for the HID Report Descriptor. We - * know what devices we are talking to, so this is by no means meant - * to be generic. We can make some safe assumptions: - * - * - We know there are no LONG tags, all short - * - We know that we have no MAIN Feature and MAIN Output items - * - We know what the IRQ reports are supposed to look like. - * - * The main purpose of this is to use the HID report desc to figure - * out the mins and maxs of the fields in the IRQ reports. The IRQ - * reports for 400/401 change slightly if the max X is bigger than 64K. - * - */ -static void parse_hid_report_descriptor(struct gtco *device, char * report, - int length) -{ - int x,i=0; - - /* Tag primitive vars */ - __u8 prefix; - __u8 size; - __u8 tag; - __u8 type; - __u8 data = 0; - __u16 data16 = 0; - __u32 data32 = 0; - - - /* For parsing logic */ - int inputnum = 0; - __u32 usage = 0; - - /* Global Values, indexed by TAG */ - __u32 globalval[TAG_GLOB_MAX]; - __u32 oldval[TAG_GLOB_MAX]; - - /* Debug stuff */ - char maintype='x'; - char globtype[12]; - int indent=0; - char indentstr[10]=""; - - - - dbg("======>>>>>>PARSE<<<<<<======"); - - /* Walk this report and pull out the info we need */ - while (imax_X == 0){ - device->max_X = globalval[TAG_GLOB_LOG_MAX]; - device->min_X = globalval[TAG_GLOB_LOG_MIN]; - } - - break; - case 1: /* Y coord */ - dbg("GER: Y Usage: 0x%x",usage); - if (device->max_Y == 0){ - device->max_Y = globalval[TAG_GLOB_LOG_MAX]; - device->min_Y = globalval[TAG_GLOB_LOG_MIN]; - } - break; - default: - /* Tilt X */ - if (usage == DIGITIZER_USAGE_TILT_X){ - if (device->maxtilt_X == 0){ - device->maxtilt_X = globalval[TAG_GLOB_LOG_MAX]; - device->mintilt_X = globalval[TAG_GLOB_LOG_MIN]; - } - } - - /* Tilt Y */ - if (usage == DIGITIZER_USAGE_TILT_Y){ - if (device->maxtilt_Y == 0){ - device->maxtilt_Y = globalval[TAG_GLOB_LOG_MAX]; - device->mintilt_Y = globalval[TAG_GLOB_LOG_MIN]; - } - } - - - /* Pressure */ - if (usage == DIGITIZER_USAGE_TIP_PRESSURE){ - if (device->maxpressure == 0){ - device->maxpressure = globalval[TAG_GLOB_LOG_MAX]; - device->minpressure = globalval[TAG_GLOB_LOG_MIN]; - } - } - - break; - } - - inputnum++; - - - break; - case TAG_MAIN_OUTPUT: - maintype='O'; - break; - case TAG_MAIN_FEATURE: - maintype='F'; - break; - case TAG_MAIN_COL_START: - maintype='S'; - - if (data==0){ - dbg("======>>>>>> Physical"); - strcpy(globtype,"Physical"); - }else{ - dbg("======>>>>>>"); - } - - /* Indent the debug output */ - indent++; - for (x=0;xusage == 0){ - device->usage = data; - } - strcpy(globtype,"USAGE"); - break; - case TAG_GLOB_LOG_MIN : - strcpy(globtype,"LOG_MIN"); - break; - case TAG_GLOB_LOG_MAX : - strcpy(globtype,"LOG_MAX"); - break; - case TAG_GLOB_PHYS_MIN : - strcpy(globtype,"PHYS_MIN"); - break; - case TAG_GLOB_PHYS_MAX : - strcpy(globtype,"PHYS_MAX"); - break; - case TAG_GLOB_UNIT_EXP : - strcpy(globtype,"EXP"); - break; - case TAG_GLOB_UNIT : - strcpy(globtype,"UNIT"); - break; - case TAG_GLOB_REPORT_SZ : - strcpy(globtype,"REPORT_SZ"); - break; - case TAG_GLOB_REPORT_ID : - strcpy(globtype,"REPORT_ID"); - /* New report, restart numbering */ - inputnum=0; - break; - case TAG_GLOB_REPORT_CNT: - strcpy(globtype,"REPORT_CNT"); - break; - case TAG_GLOB_PUSH : - strcpy(globtype,"PUSH"); - break; - case TAG_GLOB_POP: - strcpy(globtype,"POP"); - break; - } - - - /* Check to make sure we have a good tag number - so we don't overflow array */ - if (tag < TAG_GLOB_MAX){ - switch (size){ - case 1: - dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data); - globalval[tag]=data; - break; - case 2: - dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data16); - globalval[tag]=data16; - break; - case 4: - dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data32); - globalval[tag]=data32; - break; - } - }else{ - dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ", - indentstr,tag,size); - } - - - break; - - case TYPE_LOCAL: - switch(tag){ - case TAG_GLOB_USAGE: - strcpy(globtype,"USAGE"); - /* Always 1 byte */ - usage = data; - break; - case TAG_GLOB_LOG_MIN : - strcpy(globtype,"MIN"); - break; - case TAG_GLOB_LOG_MAX : - strcpy(globtype,"MAX"); - break; - default: - strcpy(globtype,"UNKNOWN"); - } - - switch (size){ - case 1: - dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", - indentstr,tag,globtype,size,data); - break; - case 2: - dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", - indentstr,tag,globtype,size,data16); - break; - case 4: - dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x", - indentstr,tag,globtype,size,data32); - break; - } - - break; - } - - } - -} - - - -/* INPUT DRIVER Routines */ - - -/* - * Called when opening the input device. This will submit the URB to - * the usb system so we start getting reports - */ -static int gtco_input_open(struct input_dev *inputdev) -{ - struct gtco *device; - device = inputdev->private; - - device->urbinfo->dev = device->usbdev; - if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) { - return -EIO; - } - return 0; -} - -/** - Called when closing the input device. This will unlink the URB -*/ -static void gtco_input_close(struct input_dev *inputdev) -{ - struct gtco *device = inputdev->private; - - usb_kill_urb(device->urbinfo); - -} - - -/* - * Setup input device capabilities. Tell the input system what this - * device is capable of generating. - * - * This information is based on what is read from the HID report and - * placed in the struct gtco structure - * - */ -static void gtco_setup_caps(struct input_dev *inputdev) -{ - struct gtco *device = inputdev->private; - - - /* Which events */ - inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC); - - - /* Misc event menu block */ - inputdev->mscbit[0] = BIT(MSC_SCAN)|BIT(MSC_SERIAL)|BIT(MSC_RAW) ; - - - /* Absolute values based on HID report info */ - input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X, - 0, 0); - input_set_abs_params(inputdev, ABS_Y, device->min_Y, device->max_Y, - 0, 0); - - /* Proximity */ - input_set_abs_params(inputdev, ABS_DISTANCE, 0, 1, 0, 0); - - /* Tilt & pressure */ - input_set_abs_params(inputdev, ABS_TILT_X, device->mintilt_X, - device->maxtilt_X, 0, 0); - input_set_abs_params(inputdev, ABS_TILT_Y, device->mintilt_Y, - device->maxtilt_Y, 0, 0); - input_set_abs_params(inputdev, ABS_PRESSURE, device->minpressure, - device->maxpressure, 0, 0); - - - /* Transducer */ - input_set_abs_params(inputdev, ABS_MISC, 0,0xFF, 0, 0); - -} - - - -/* USB Routines */ - - -/* - * URB callback routine. Called when we get IRQ reports from the - * digitizer. - * - * This bridges the USB and input device worlds. It generates events - * on the input device based on the USB reports. - */ -static void gtco_urb_callback(struct urb *urbinfo) -{ - - - struct gtco *device = urbinfo->context; - struct input_dev *inputdev; - int rc; - u32 val = 0; - s8 valsigned = 0; - char le_buffer[2]; - - inputdev = device->inputdevice; - - - /* Was callback OK? */ - if ((urbinfo->status == -ECONNRESET ) || - (urbinfo->status == -ENOENT ) || - (urbinfo->status == -ESHUTDOWN )){ - - /* Shutdown is occurring. Return and don't queue up any more */ - return; - } - - if (urbinfo->status != 0 ) { - /* Some unknown error. Hopefully temporary. Just go and */ - /* requeue an URB */ - goto resubmit; - } - - /* - * Good URB, now process - */ - - /* PID dependent when we interpret the report */ - if ((inputdev->id.product == PID_1000 )|| - (inputdev->id.product == PID_1001 )|| - (inputdev->id.product == PID_1002 )) - { - - /* - * Switch on the report ID - * Conveniently, the reports have more information, the higher - * the report number. We can just fall through the case - * statements if we start with the highest number report - */ - switch(device->buffer[0]){ - case 5: - /* Pressure is 9 bits */ - val = ((u16)(device->buffer[8]) << 1); - val |= (u16)(device->buffer[7] >> 7); - input_report_abs(inputdev, ABS_PRESSURE, - device->buffer[8]); - - /* Mask out the Y tilt value used for pressure */ - device->buffer[7] = (u8)((device->buffer[7]) & 0x7F); - - - /* Fall thru */ - case 4: - /* Tilt */ - - /* Sign extend these 7 bit numbers. */ - if (device->buffer[6] & 0x40) - device->buffer[6] |= 0x80; - - if (device->buffer[7] & 0x40) - device->buffer[7] |= 0x80; - - - valsigned = (device->buffer[6]); - input_report_abs(inputdev, ABS_TILT_X, (s32)valsigned); - - valsigned = (device->buffer[7]); - input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned); - - /* Fall thru */ - - case 2: - case 3: - /* Convert buttons, only 5 bits possible */ - val = (device->buffer[5])&MASK_BUTTON; - - /* We don't apply any meaning to the bitmask, - just report */ - input_event(inputdev, EV_MSC, MSC_SERIAL, val); - - /* Fall thru */ - case 1: - - /* All reports have X and Y coords in the same place */ - val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[1]))); - input_report_abs(inputdev, ABS_X, val); - - val = le16_to_cpu(get_unaligned((__le16 *) &(device->buffer[3]))); - input_report_abs(inputdev, ABS_Y, val); - - - /* Ditto for proximity bit */ - if (device->buffer[5]& MASK_INRANGE){ - val = 1; - }else{ - val=0; - } - input_report_abs(inputdev, ABS_DISTANCE, val); - - - /* Report 1 is an exception to how we handle buttons */ - /* Buttons are an index, not a bitmask */ - if (device->buffer[0] == 1){ - - /* Convert buttons, 5 bit index */ - /* Report value of index set as one, - the rest as 0 */ - val = device->buffer[5]& MASK_BUTTON; - dbg("======>>>>>>REPORT 1: val 0x%X(%d)", - val,val); - - /* - * We don't apply any meaning to the button - * index, just report it - */ - input_event(inputdev, EV_MSC, MSC_SERIAL, val); - - - } - - break; - case 7: - /* Menu blocks */ - input_event(inputdev, EV_MSC, MSC_SCAN, - device->buffer[1]); - - - break; - - } - - - } - /* Other pid class */ - if ((inputdev->id.product == PID_400 )|| - (inputdev->id.product == PID_401 )) - { - - /* Report 2 */ - if (device->buffer[0] == 2){ - /* Menu blocks */ - input_event(inputdev, EV_MSC, MSC_SCAN, - device->buffer[1]); - } - - /* Report 1 */ - if (device->buffer[0] == 1){ - char buttonbyte; - - - /* IF X max > 64K, we still a bit from the y report */ - if (device->max_X > 0x10000){ - - val = (u16)(((u16)(device->buffer[2]<<8))|((u8)(device->buffer[1]))); - val |= (u32)(((u8)device->buffer[3]&0x1)<< 16); - - input_report_abs(inputdev, ABS_X, val); - - le_buffer[0] = (u8)((u8)(device->buffer[3])>>1); - le_buffer[0] |= (u8)((device->buffer[3]&0x1)<<7); - - le_buffer[1] = (u8)(device->buffer[4]>>1); - le_buffer[1] |= (u8)((device->buffer[5]&0x1)<<7); - - val = le16_to_cpu(get_unaligned((__le16 *)(le_buffer))); - - input_report_abs(inputdev, ABS_Y, val); - - - /* - * Shift the button byte right by one to - * make it look like the standard report - */ - buttonbyte = (device->buffer[5])>>1; - }else{ - - val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[1])))); - input_report_abs(inputdev, ABS_X, val); - - val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[3])))); - input_report_abs(inputdev, ABS_Y, val); - - buttonbyte = device->buffer[5]; - - } - - - /* BUTTONS and PROXIMITY */ - if (buttonbyte& MASK_INRANGE){ - val = 1; - }else{ - val=0; - } - input_report_abs(inputdev, ABS_DISTANCE, val); - - /* Convert buttons, only 4 bits possible */ - val = buttonbyte&0x0F; -#ifdef USE_BUTTONS - for ( i=0;i<5;i++){ - input_report_key(inputdev, BTN_DIGI+i,val&(1<buffer[6]); - - } - } - - /* Everybody gets report ID's */ - input_event(inputdev, EV_MSC, MSC_RAW, device->buffer[0]); - - /* Sync it up */ - input_sync(inputdev); - - resubmit: - rc = usb_submit_urb(urbinfo, GFP_ATOMIC); - if (rc != 0) { - err("usb_submit_urb failed rc=0x%x",rc); - } - -} - -/* - * The probe routine. This is called when the kernel find the matching USB - * vendor/product. We do the following: - * - * - Allocate mem for a local structure to manage the device - * - Request a HID Report Descriptor from the device and parse it to - * find out the device parameters - * - Create an input device and assign it attributes - * - Allocate an URB so the device can talk to us when the input - * queue is open - */ -static int gtco_probe(struct usb_interface *usbinterface, - const struct usb_device_id *id) -{ - - struct gtco *device = NULL; - char path[PATHLENGTH]; - struct input_dev *inputdev; - struct hid_descriptor *hid_desc; - char *report; - int result=0, retry; - struct usb_endpoint_descriptor *endpoint; - - /* Allocate memory for device structure */ - device = kzalloc(sizeof(struct gtco), GFP_KERNEL); - if (device == NULL) { - err("No more memory"); - return -ENOMEM; - } - - - device->inputdevice = input_allocate_device(); - if (!device->inputdevice){ - kfree(device); - err("No more memory"); - return -ENOMEM; - } - - /* Get pointer to the input device */ - inputdev = device->inputdevice; - - /* Save interface information */ - device->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); - - - /* Allocate some data for incoming reports */ - device->buffer = usb_buffer_alloc(device->usbdev, REPORT_MAX_SIZE, - GFP_KERNEL, &(device->buf_dma)); - if (!device->buffer){ - input_free_device(device->inputdevice); - kfree(device); - err("No more memory"); - return -ENOMEM; - } - - /* Allocate URB for reports */ - device->urbinfo = usb_alloc_urb(0, GFP_KERNEL); - if (!device->urbinfo) { - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - input_free_device(device->inputdevice); - kfree(device); - err("No more memory"); - return -ENOMEM; - } - - - /* - * The endpoint is always altsetting 0, we know this since we know - * this device only has one interrupt endpoint - */ - endpoint = &usbinterface->altsetting[0].endpoint[0].desc; - - /* Some debug */ - dbg("gtco # interfaces: %d",usbinterface->num_altsetting); - dbg("num endpoints: %d",usbinterface->cur_altsetting->desc.bNumEndpoints); - dbg("interface class: %d",usbinterface->cur_altsetting->desc.bInterfaceClass); - dbg("endpoint: attribute:0x%x type:0x%x",endpoint->bmAttributes,endpoint->bDescriptorType); - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) - dbg("endpoint: we have interrupt endpoint\n"); - - dbg("endpoint extra len:%d ",usbinterface->altsetting[0].extralen); - - - - /* - * Find the HID descriptor so we can find out the size of the - * HID report descriptor - */ - if (usb_get_extra_descriptor(usbinterface->cur_altsetting, - HID_DEVICE_TYPE,&hid_desc) != 0){ - err("Can't retrieve exta USB descriptor to get hid report descriptor length"); - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - input_free_device(device->inputdevice); - kfree(device); - return -EIO; - } - - dbg("Extra descriptor success: type:%d len:%d", - hid_desc->bDescriptorType, hid_desc->wDescriptorLength); - - if (!(report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL))) { - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - - input_free_device(device->inputdevice); - kfree(device); - err("No more memory"); - return -ENOMEM; - } - - /* Couple of tries to get reply */ - for (retry=0;retry<3;retry++) { - result = usb_control_msg(device->usbdev, - usb_rcvctrlpipe(device->usbdev, 0), - USB_REQ_GET_DESCRIPTOR, - USB_RECIP_INTERFACE | USB_DIR_IN, - (REPORT_DEVICE_TYPE << 8), - 0, /* interface */ - report, - hid_desc->wDescriptorLength, - 5000); /* 5 secs */ - - if (result == hid_desc->wDescriptorLength) - break; - } - - /* If we didn't get the report, fail */ - dbg("usb_control_msg result: :%d", result); - if (result != hid_desc->wDescriptorLength){ - kfree(report); - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - input_free_device(device->inputdevice); - kfree(device); - err("Failed to get HID Report Descriptor of size: %d", - hid_desc->wDescriptorLength); - return -EIO; - } - - - /* Now we parse the report */ - parse_hid_report_descriptor(device,report,result); - - /* Now we delete it */ - kfree(report); - - /* Create a device file node */ - usb_make_path(device->usbdev, path, PATHLENGTH); - sprintf(device->usbpath, "%s/input0", path); - - - /* Set Input device functions */ - inputdev->open = gtco_input_open; - inputdev->close = gtco_input_close; - - /* Set input device information */ - inputdev->name = "GTCO_CalComp"; - inputdev->phys = device->usbpath; - inputdev->private = device; - - - /* Now set up all the input device capabilities */ - gtco_setup_caps(inputdev); - - /* Set input device required ID information */ - usb_to_input_id(device->usbdev, &device->inputdevice->id); - inputdev->cdev.dev = &usbinterface->dev; - - /* Setup the URB, it will be posted later on open of input device */ - endpoint = &usbinterface->altsetting[0].endpoint[0].desc; - - usb_fill_int_urb(device->urbinfo, - device->usbdev, - usb_rcvintpipe(device->usbdev, - endpoint->bEndpointAddress), - device->buffer, - REPORT_MAX_SIZE, - gtco_urb_callback, - device, - endpoint->bInterval); - - device->urbinfo->transfer_dma = device->buf_dma; - device->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - - /* Save device pointer in USB interface device */ - usb_set_intfdata(usbinterface, device); - - /* All done, now register the input device */ - input_register_device(inputdev); - - info( "gtco driver created usb: %s\n", path); - return 0; - -} - -/* - * This function is a standard USB function called when the USB device - * is disconnected. We will get rid of the URV, de-register the input - * device, and free up allocated memory - */ -static void gtco_disconnect(struct usb_interface *interface) -{ - - /* Grab private device ptr */ - struct gtco *device = usb_get_intfdata (interface); - struct input_dev *inputdev; - - inputdev = device->inputdevice; - - /* Now reverse all the registration stuff */ - if (device) { - input_unregister_device(inputdev); - usb_kill_urb(device->urbinfo); - usb_free_urb(device->urbinfo); - usb_buffer_free(device->usbdev, REPORT_MAX_SIZE, - device->buffer, device->buf_dma); - kfree(device); - } - - info("gtco driver disconnected"); -} - - -/* STANDARD MODULE LOAD ROUTINES */ - -static struct usb_driver gtco_driverinfo_table = { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) - .owner = THIS_MODULE, -#endif - .name = "gtco", - .id_table = gtco_usbid_table, - .probe = gtco_probe, - .disconnect = gtco_disconnect, -}; -/* - * Register this module with the USB subsystem - */ -static int __init gtco_init(void) -{ - int rc; - rc = usb_register(>co_driverinfo_table); - if (rc) { - err("usb_register() failed rc=0x%x", rc); - } - printk("GTCO usb driver version: %s",GTCO_VERSION); - return rc; -} - -/* - * Deregister this module with the USB subsystem - */ -static void __exit gtco_exit(void) -{ - usb_deregister(>co_driverinfo_table); -} - -module_init (gtco_init); -module_exit (gtco_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/input/hid-core.c b/trunk/drivers/usb/input/hid-core.c index 84983d1b7164..e07a30490726 100644 --- a/trunk/drivers/usb/input/hid-core.c +++ b/trunk/drivers/usb/input/hid-core.c @@ -768,9 +768,6 @@ void usbhid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_PANTHERLORD 0x0810 #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 -#define USB_VENDOR_ID_SONY 0x054c -#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 - /* * Alphabetically sorted blacklist by quirk type. */ @@ -952,8 +949,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, - { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER }, - { 0, 0 } }; @@ -1018,32 +1013,6 @@ static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) } } -/* - * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller - * to "operational". Without this, the ps3 controller will not report any - * events. - */ -static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum) -{ - int result; - char *buf = kmalloc(18, GFP_KERNEL); - - if (!buf) - return; - - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - HID_REQ_GET_REPORT, - USB_DIR_IN | USB_TYPE_CLASS | - USB_RECIP_INTERFACE, - (3 << 8) | 0xf2, ifnum, buf, 17, - USB_CTRL_GET_TIMEOUT); - - if (result < 0) - err("%s failed: %d\n", __func__, result); - - kfree(buf); -} - static struct hid_device *usb_hid_configure(struct usb_interface *intf) { struct usb_host_interface *interface = intf->cur_altsetting; @@ -1334,10 +1303,6 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) if ((hid->claimed & HID_CLAIMED_INPUT)) hid_ff_init(hid); - if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER) - hid_fixup_sony_ps3_controller(interface_to_usbdev(intf), - intf->cur_altsetting->desc.bInterfaceNumber); - printk(KERN_INFO); if (hid->claimed & HID_CLAIMED_INPUT) diff --git a/trunk/drivers/usb/input/hid-lgff.c b/trunk/drivers/usb/input/hid-lgff.c index 4f4fc3be192e..e47466268565 100644 --- a/trunk/drivers/usb/input/hid-lgff.c +++ b/trunk/drivers/usb/input/hid-lgff.c @@ -32,7 +32,7 @@ #include #include "usbhid.h" -struct dev_type { +struct device_type { u16 idVendor; u16 idProduct; const signed short *ff; @@ -48,7 +48,7 @@ static const signed short ff_joystick[] = { -1 }; -static const struct dev_type devices[] = { +static const struct device_type devices[] = { { 0x046d, 0xc211, ff_rumble }, { 0x046d, 0xc219, ff_rumble }, { 0x046d, 0xc283, ff_joystick }, diff --git a/trunk/drivers/usb/misc/idmouse.c b/trunk/drivers/usb/misc/idmouse.c index 15c70bd048c4..c9418535bef8 100644 --- a/trunk/drivers/usb/misc/idmouse.c +++ b/trunk/drivers/usb/misc/idmouse.c @@ -269,7 +269,7 @@ static int idmouse_release(struct inode *inode, struct file *file) /* prevent a race condition with open() */ mutex_lock(&disconnect_mutex); - dev = file->private_data; + dev = (struct usb_idmouse *) file->private_data; if (dev == NULL) { mutex_unlock(&disconnect_mutex); @@ -304,15 +304,17 @@ static int idmouse_release(struct inode *inode, struct file *file) static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) { - struct usb_idmouse *dev = file->private_data; + struct usb_idmouse *dev; int result; + dev = (struct usb_idmouse *) file->private_data; + /* lock this object */ - down(&dev->sem); + down (&dev->sem); /* verify that the device wasn't unplugged */ if (!dev->present) { - up(&dev->sem); + up (&dev->sem); return -ENODEV; } diff --git a/trunk/drivers/usb/misc/rio500.c b/trunk/drivers/usb/misc/rio500.c index fdf68479a166..384fa3769805 100644 --- a/trunk/drivers/usb/misc/rio500.c +++ b/trunk/drivers/usb/misc/rio500.c @@ -69,7 +69,7 @@ struct rio_usb_data { char *obuf, *ibuf; /* transfer buffers */ char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */ wait_queue_head_t wait_q; /* for timeouts */ - struct mutex lock; /* general race avoidance */ + struct semaphore lock; /* general race avoidance */ }; static struct rio_usb_data rio_instance; @@ -78,17 +78,17 @@ static int open_rio(struct inode *inode, struct file *file) { struct rio_usb_data *rio = &rio_instance; - mutex_lock(&(rio->lock)); + down(&(rio->lock)); if (rio->isopen || !rio->present) { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return -EBUSY; } rio->isopen = 1; init_waitqueue_head(&rio->wait_q); - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); info("Rio opened."); @@ -117,7 +117,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, int retries; int retval=0; - mutex_lock(&(rio->lock)); + down(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ if ( rio == NULL || rio->present == 0 || @@ -257,7 +257,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, err_out: - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return retval; } @@ -275,17 +275,14 @@ write_rio(struct file *file, const char __user *buffer, int result = 0; int maxretry; int errn = 0; - int intr; - intr = mutex_lock_interruptible(&(rio->lock)); - if (intr) - return -EINTR; + down(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ if ( rio == NULL || rio->present == 0 || rio->rio_dev == NULL ) { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return -ENODEV; } @@ -308,7 +305,7 @@ write_rio(struct file *file, const char __user *buffer, goto error; } if (signal_pending(current)) { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return bytes_written ? bytes_written : -EINTR; } @@ -344,12 +341,12 @@ write_rio(struct file *file, const char __user *buffer, buffer += copy_size; } while (count > 0); - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return bytes_written ? bytes_written : -EIO; error: - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return errn; } @@ -364,17 +361,14 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) int result; int maxretry = 10; char *ibuf; - int intr; - intr = mutex_lock_interruptible(&(rio->lock)); - if (intr) - return -EINTR; + down(&(rio->lock)); /* Sanity check to make sure rio is connected, powered, etc */ if ( rio == NULL || rio->present == 0 || rio->rio_dev == NULL ) { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return -ENODEV; } @@ -385,11 +379,11 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) while (count > 0) { if (signal_pending(current)) { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return read_count ? read_count : -EINTR; } if (!rio->rio_dev) { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return -ENODEV; } this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count; @@ -406,7 +400,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) count = this_read = partial; } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */ if (!maxretry--) { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); err("read_rio: maxretry timeout"); return -ETIME; } @@ -415,18 +409,18 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) finish_wait(&rio->wait_q, &wait); continue; } else if (result != -EREMOTEIO) { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); err("Read Whoops - result:%u partial:%u this_read:%u", result, partial, this_read); return -EIO; } else { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return (0); } if (this_read) { if (copy_to_user(buffer, ibuf, this_read)) { - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return -EFAULT; } count -= this_read; @@ -434,7 +428,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) buffer += this_read; } } - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return read_count; } @@ -486,7 +480,7 @@ static int probe_rio(struct usb_interface *intf, } dbg("probe_rio: ibuf address:%p", rio->ibuf); - mutex_init(&(rio->lock)); + init_MUTEX(&(rio->lock)); usb_set_intfdata (intf, rio); rio->present = 1; @@ -502,12 +496,12 @@ static void disconnect_rio(struct usb_interface *intf) if (rio) { usb_deregister_dev(intf, &usb_rio_class); - mutex_lock(&(rio->lock)); + down(&(rio->lock)); if (rio->isopen) { rio->isopen = 0; /* better let it finish - the release will do whats needed */ rio->rio_dev = NULL; - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); return; } kfree(rio->ibuf); @@ -516,7 +510,7 @@ static void disconnect_rio(struct usb_interface *intf) info("USB Rio disconnected."); rio->present = 0; - mutex_unlock(&(rio->lock)); + up(&(rio->lock)); } } diff --git a/trunk/drivers/usb/mon/Makefile b/trunk/drivers/usb/mon/Makefile index 90c59535778d..3cf3ea3a88ed 100644 --- a/trunk/drivers/usb/mon/Makefile +++ b/trunk/drivers/usb/mon/Makefile @@ -2,7 +2,7 @@ # Makefile for USB Core files and filesystem # -usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o mon_dma.o +usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_dma.o # This does not use CONFIG_USB_MON because we want this to use a tristate. obj-$(CONFIG_USB) += usbmon.o diff --git a/trunk/drivers/usb/mon/mon_bin.c b/trunk/drivers/usb/mon/mon_bin.c deleted file mode 100644 index c01dfe603672..000000000000 --- a/trunk/drivers/usb/mon/mon_bin.c +++ /dev/null @@ -1,1172 +0,0 @@ -/* - * The USB Monitor, inspired by Dave Harding's USBMon. - * - * This is a binary format reader. - * - * Copyright (C) 2006 Paolo Abeni (paolo.abeni@email.it) - * Copyright (C) 2006 Pete Zaitcev (zaitcev@redhat.com) - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "usb_mon.h" - -/* - * Defined by USB 2.0 clause 9.3, table 9.2. - */ -#define SETUP_LEN 8 - -/* ioctl macros */ -#define MON_IOC_MAGIC 0x92 - -#define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1) -/* #2 used to be MON_IOCX_URB, removed before it got into Linus tree */ -#define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats) -#define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4) -#define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5) -#define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get) -#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch) -#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8) -#ifdef CONFIG_COMPAT -#define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32) -#define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32) -#endif - -/* - * Some architectures have enormous basic pages (16KB for ia64, 64KB for ppc). - * But it's all right. Just use a simple way to make sure the chunk is never - * smaller than a page. - * - * N.B. An application does not know our chunk size. - * - * Woops, get_zeroed_page() returns a single page. I guess we're stuck with - * page-sized chunks for the time being. - */ -#define CHUNK_SIZE PAGE_SIZE -#define CHUNK_ALIGN(x) (((x)+CHUNK_SIZE-1) & ~(CHUNK_SIZE-1)) - -/* - * The magic limit was calculated so that it allows the monitoring - * application to pick data once in two ticks. This way, another application, - * which presumably drives the bus, gets to hog CPU, yet we collect our data. - * If HZ is 100, a 480 mbit/s bus drives 614 KB every jiffy. USB has an - * enormous overhead built into the bus protocol, so we need about 1000 KB. - * - * This is still too much for most cases, where we just snoop a few - * descriptor fetches for enumeration. So, the default is a "reasonable" - * amount for systems with HZ=250 and incomplete bus saturation. - * - * XXX What about multi-megabyte URBs which take minutes to transfer? - */ -#define BUFF_MAX CHUNK_ALIGN(1200*1024) -#define BUFF_DFL CHUNK_ALIGN(300*1024) -#define BUFF_MIN CHUNK_ALIGN(8*1024) - -/* - * The per-event API header (2 per URB). - * - * This structure is seen in userland as defined by the documentation. - */ -struct mon_bin_hdr { - u64 id; /* URB ID - from submission to callback */ - unsigned char type; /* Same as in text API; extensible. */ - unsigned char xfer_type; /* ISO, Intr, Control, Bulk */ - unsigned char epnum; /* Endpoint number and transfer direction */ - unsigned char devnum; /* Device address */ - unsigned short busnum; /* Bus number */ - char flag_setup; - char flag_data; - s64 ts_sec; /* gettimeofday */ - s32 ts_usec; /* gettimeofday */ - int status; - unsigned int len_urb; /* Length of data (submitted or actual) */ - unsigned int len_cap; /* Delivered length */ - unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ -}; - -/* per file statistic */ -struct mon_bin_stats { - u32 queued; - u32 dropped; -}; - -struct mon_bin_get { - struct mon_bin_hdr __user *hdr; /* Only 48 bytes, not 64. */ - void __user *data; - size_t alloc; /* Length of data (can be zero) */ -}; - -struct mon_bin_mfetch { - u32 __user *offvec; /* Vector of events fetched */ - u32 nfetch; /* Number of events to fetch (out: fetched) */ - u32 nflush; /* Number of events to flush */ -}; - -#ifdef CONFIG_COMPAT -struct mon_bin_get32 { - u32 hdr32; - u32 data32; - u32 alloc32; -}; - -struct mon_bin_mfetch32 { - u32 offvec32; - u32 nfetch32; - u32 nflush32; -}; -#endif - -/* Having these two values same prevents wrapping of the mon_bin_hdr */ -#define PKT_ALIGN 64 -#define PKT_SIZE 64 - -/* max number of USB bus supported */ -#define MON_BIN_MAX_MINOR 128 - -/* - * The buffer: map of used pages. - */ -struct mon_pgmap { - struct page *pg; - unsigned char *ptr; /* XXX just use page_to_virt everywhere? */ -}; - -/* - * This gets associated with an open file struct. - */ -struct mon_reader_bin { - /* The buffer: one per open. */ - spinlock_t b_lock; /* Protect b_cnt, b_in */ - unsigned int b_size; /* Current size of the buffer - bytes */ - unsigned int b_cnt; /* Bytes used */ - unsigned int b_in, b_out; /* Offsets into buffer - bytes */ - unsigned int b_read; /* Amount of read data in curr. pkt. */ - struct mon_pgmap *b_vec; /* The map array */ - wait_queue_head_t b_wait; /* Wait for data here */ - - struct mutex fetch_lock; /* Protect b_read, b_out */ - int mmap_active; - - /* A list of these is needed for "bus 0". Some time later. */ - struct mon_reader r; - - /* Stats */ - unsigned int cnt_lost; -}; - -static inline struct mon_bin_hdr *MON_OFF2HDR(const struct mon_reader_bin *rp, - unsigned int offset) -{ - return (struct mon_bin_hdr *) - (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE); -} - -#define MON_RING_EMPTY(rp) ((rp)->b_cnt == 0) - -static dev_t mon_bin_dev0; -static struct cdev mon_bin_cdev; - -static void mon_buff_area_fill(const struct mon_reader_bin *rp, - unsigned int offset, unsigned int size); -static int mon_bin_wait_event(struct file *file, struct mon_reader_bin *rp); -static int mon_alloc_buff(struct mon_pgmap *map, int npages); -static void mon_free_buff(struct mon_pgmap *map, int npages); - -/* - * This is a "chunked memcpy". It does not manipulate any counters. - * But it returns the new offset for repeated application. - */ -unsigned int mon_copy_to_buff(const struct mon_reader_bin *this, - unsigned int off, const unsigned char *from, unsigned int length) -{ - unsigned int step_len; - unsigned char *buf; - unsigned int in_page; - - while (length) { - /* - * Determine step_len. - */ - step_len = length; - in_page = CHUNK_SIZE - (off & (CHUNK_SIZE-1)); - if (in_page < step_len) - step_len = in_page; - - /* - * Copy data and advance pointers. - */ - buf = this->b_vec[off / CHUNK_SIZE].ptr + off % CHUNK_SIZE; - memcpy(buf, from, step_len); - if ((off += step_len) >= this->b_size) off = 0; - from += step_len; - length -= step_len; - } - return off; -} - -/* - * This is a little worse than the above because it's "chunked copy_to_user". - * The return value is an error code, not an offset. - */ -static int copy_from_buf(const struct mon_reader_bin *this, unsigned int off, - char __user *to, int length) -{ - unsigned int step_len; - unsigned char *buf; - unsigned int in_page; - - while (length) { - /* - * Determine step_len. - */ - step_len = length; - in_page = CHUNK_SIZE - (off & (CHUNK_SIZE-1)); - if (in_page < step_len) - step_len = in_page; - - /* - * Copy data and advance pointers. - */ - buf = this->b_vec[off / CHUNK_SIZE].ptr + off % CHUNK_SIZE; - if (copy_to_user(to, buf, step_len)) - return -EINVAL; - if ((off += step_len) >= this->b_size) off = 0; - to += step_len; - length -= step_len; - } - return 0; -} - -/* - * Allocate an (aligned) area in the buffer. - * This is called under b_lock. - * Returns ~0 on failure. - */ -static unsigned int mon_buff_area_alloc(struct mon_reader_bin *rp, - unsigned int size) -{ - unsigned int offset; - - size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1); - if (rp->b_cnt + size > rp->b_size) - return ~0; - offset = rp->b_in; - rp->b_cnt += size; - if ((rp->b_in += size) >= rp->b_size) - rp->b_in -= rp->b_size; - return offset; -} - -/* - * This is the same thing as mon_buff_area_alloc, only it does not allow - * buffers to wrap. This is needed by applications which pass references - * into mmap-ed buffers up their stacks (libpcap can do that). - * - * Currently, we always have the header stuck with the data, although - * it is not strictly speaking necessary. - * - * When a buffer would wrap, we place a filler packet to mark the space. - */ -static unsigned int mon_buff_area_alloc_contiguous(struct mon_reader_bin *rp, - unsigned int size) -{ - unsigned int offset; - unsigned int fill_size; - - size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1); - if (rp->b_cnt + size > rp->b_size) - return ~0; - if (rp->b_in + size > rp->b_size) { - /* - * This would wrap. Find if we still have space after - * skipping to the end of the buffer. If we do, place - * a filler packet and allocate a new packet. - */ - fill_size = rp->b_size - rp->b_in; - if (rp->b_cnt + size + fill_size > rp->b_size) - return ~0; - mon_buff_area_fill(rp, rp->b_in, fill_size); - - offset = 0; - rp->b_in = size; - rp->b_cnt += size + fill_size; - } else if (rp->b_in + size == rp->b_size) { - offset = rp->b_in; - rp->b_in = 0; - rp->b_cnt += size; - } else { - offset = rp->b_in; - rp->b_in += size; - rp->b_cnt += size; - } - return offset; -} - -/* - * Return a few (kilo-)bytes to the head of the buffer. - * This is used if a DMA fetch fails. - */ -static void mon_buff_area_shrink(struct mon_reader_bin *rp, unsigned int size) -{ - - size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1); - rp->b_cnt -= size; - if (rp->b_in < size) - rp->b_in += rp->b_size; - rp->b_in -= size; -} - -/* - * This has to be called under both b_lock and fetch_lock, because - * it accesses both b_cnt and b_out. - */ -static void mon_buff_area_free(struct mon_reader_bin *rp, unsigned int size) -{ - - size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1); - rp->b_cnt -= size; - if ((rp->b_out += size) >= rp->b_size) - rp->b_out -= rp->b_size; -} - -static void mon_buff_area_fill(const struct mon_reader_bin *rp, - unsigned int offset, unsigned int size) -{ - struct mon_bin_hdr *ep; - - ep = MON_OFF2HDR(rp, offset); - memset(ep, 0, PKT_SIZE); - ep->type = '@'; - ep->len_cap = size - PKT_SIZE; -} - -static inline char mon_bin_get_setup(unsigned char *setupb, - const struct urb *urb, char ev_type) -{ - - if (!usb_pipecontrol(urb->pipe) || ev_type != 'S') - return '-'; - - if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP) - return mon_dmapeek(setupb, urb->setup_dma, SETUP_LEN); - if (urb->setup_packet == NULL) - return 'Z'; - - memcpy(setupb, urb->setup_packet, SETUP_LEN); - return 0; -} - -static char mon_bin_get_data(const struct mon_reader_bin *rp, - unsigned int offset, struct urb *urb, unsigned int length) -{ - - if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) { - mon_dmapeek_vec(rp, offset, urb->transfer_dma, length); - return 0; - } - - if (urb->transfer_buffer == NULL) - return 'Z'; - - mon_copy_to_buff(rp, offset, urb->transfer_buffer, length); - return 0; -} - -static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, - char ev_type) -{ - unsigned long flags; - struct timeval ts; - unsigned int urb_length; - unsigned int offset; - unsigned int length; - struct mon_bin_hdr *ep; - char data_tag = 0; - - do_gettimeofday(&ts); - - spin_lock_irqsave(&rp->b_lock, flags); - - /* - * Find the maximum allowable length, then allocate space. - */ - urb_length = (ev_type == 'S') ? - urb->transfer_buffer_length : urb->actual_length; - length = urb_length; - - if (length >= rp->b_size/5) - length = rp->b_size/5; - - if (usb_pipein(urb->pipe)) { - if (ev_type == 'S') { - length = 0; - data_tag = '<'; - } - } else { - if (ev_type == 'C') { - length = 0; - data_tag = '>'; - } - } - - if (rp->mmap_active) - offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE); - else - offset = mon_buff_area_alloc(rp, length + PKT_SIZE); - if (offset == ~0) { - rp->cnt_lost++; - spin_unlock_irqrestore(&rp->b_lock, flags); - return; - } - - ep = MON_OFF2HDR(rp, offset); - if ((offset += PKT_SIZE) >= rp->b_size) offset = 0; - - /* - * Fill the allocated area. - */ - memset(ep, 0, PKT_SIZE); - ep->type = ev_type; - ep->xfer_type = usb_pipetype(urb->pipe); - /* We use the fact that usb_pipein() returns 0x80 */ - ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe); - ep->devnum = usb_pipedevice(urb->pipe); - ep->busnum = rp->r.m_bus->u_bus->busnum; - ep->id = (unsigned long) urb; - ep->ts_sec = ts.tv_sec; - ep->ts_usec = ts.tv_usec; - ep->status = urb->status; - ep->len_urb = urb_length; - ep->len_cap = length; - - ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type); - if (length != 0) { - ep->flag_data = mon_bin_get_data(rp, offset, urb, length); - if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */ - ep->len_cap = 0; - mon_buff_area_shrink(rp, length); - } - } else { - ep->flag_data = data_tag; - } - - spin_unlock_irqrestore(&rp->b_lock, flags); - - wake_up(&rp->b_wait); -} - -static void mon_bin_submit(void *data, struct urb *urb) -{ - struct mon_reader_bin *rp = data; - mon_bin_event(rp, urb, 'S'); -} - -static void mon_bin_complete(void *data, struct urb *urb) -{ - struct mon_reader_bin *rp = data; - mon_bin_event(rp, urb, 'C'); -} - -static void mon_bin_error(void *data, struct urb *urb, int error) -{ - struct mon_reader_bin *rp = data; - unsigned long flags; - unsigned int offset; - struct mon_bin_hdr *ep; - - spin_lock_irqsave(&rp->b_lock, flags); - - offset = mon_buff_area_alloc(rp, PKT_SIZE); - if (offset == ~0) { - /* Not incrementing cnt_lost. Just because. */ - spin_unlock_irqrestore(&rp->b_lock, flags); - return; - } - - ep = MON_OFF2HDR(rp, offset); - - memset(ep, 0, PKT_SIZE); - ep->type = 'E'; - ep->xfer_type = usb_pipetype(urb->pipe); - /* We use the fact that usb_pipein() returns 0x80 */ - ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe); - ep->devnum = usb_pipedevice(urb->pipe); - ep->busnum = rp->r.m_bus->u_bus->busnum; - ep->id = (unsigned long) urb; - ep->status = error; - - ep->flag_setup = '-'; - ep->flag_data = 'E'; - - spin_unlock_irqrestore(&rp->b_lock, flags); - - wake_up(&rp->b_wait); -} - -static int mon_bin_open(struct inode *inode, struct file *file) -{ - struct mon_bus *mbus; - struct usb_bus *ubus; - struct mon_reader_bin *rp; - size_t size; - int rc; - - mutex_lock(&mon_lock); - if ((mbus = mon_bus_lookup(iminor(inode))) == NULL) { - mutex_unlock(&mon_lock); - return -ENODEV; - } - if ((ubus = mbus->u_bus) == NULL) { - printk(KERN_ERR TAG ": consistency error on open\n"); - mutex_unlock(&mon_lock); - return -ENODEV; - } - - rp = kzalloc(sizeof(struct mon_reader_bin), GFP_KERNEL); - if (rp == NULL) { - rc = -ENOMEM; - goto err_alloc; - } - spin_lock_init(&rp->b_lock); - init_waitqueue_head(&rp->b_wait); - mutex_init(&rp->fetch_lock); - - rp->b_size = BUFF_DFL; - - size = sizeof(struct mon_pgmap) * (rp->b_size/CHUNK_SIZE); - if ((rp->b_vec = kzalloc(size, GFP_KERNEL)) == NULL) { - rc = -ENOMEM; - goto err_allocvec; - } - - if ((rc = mon_alloc_buff(rp->b_vec, rp->b_size/CHUNK_SIZE)) < 0) - goto err_allocbuff; - - rp->r.m_bus = mbus; - rp->r.r_data = rp; - rp->r.rnf_submit = mon_bin_submit; - rp->r.rnf_error = mon_bin_error; - rp->r.rnf_complete = mon_bin_complete; - - mon_reader_add(mbus, &rp->r); - - file->private_data = rp; - mutex_unlock(&mon_lock); - return 0; - -err_allocbuff: - kfree(rp->b_vec); -err_allocvec: - kfree(rp); -err_alloc: - mutex_unlock(&mon_lock); - return rc; -} - -/* - * Extract an event from buffer and copy it to user space. - * Wait if there is no event ready. - * Returns zero or error. - */ -static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp, - struct mon_bin_hdr __user *hdr, void __user *data, unsigned int nbytes) -{ - unsigned long flags; - struct mon_bin_hdr *ep; - size_t step_len; - unsigned int offset; - int rc; - - mutex_lock(&rp->fetch_lock); - - if ((rc = mon_bin_wait_event(file, rp)) < 0) { - mutex_unlock(&rp->fetch_lock); - return rc; - } - - ep = MON_OFF2HDR(rp, rp->b_out); - - if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) { - mutex_unlock(&rp->fetch_lock); - return -EFAULT; - } - - step_len = min(ep->len_cap, nbytes); - if ((offset = rp->b_out + PKT_SIZE) >= rp->b_size) offset = 0; - - if (copy_from_buf(rp, offset, data, step_len)) { - mutex_unlock(&rp->fetch_lock); - return -EFAULT; - } - - spin_lock_irqsave(&rp->b_lock, flags); - mon_buff_area_free(rp, PKT_SIZE + ep->len_cap); - spin_unlock_irqrestore(&rp->b_lock, flags); - rp->b_read = 0; - - mutex_unlock(&rp->fetch_lock); - return 0; -} - -static int mon_bin_release(struct inode *inode, struct file *file) -{ - struct mon_reader_bin *rp = file->private_data; - struct mon_bus* mbus = rp->r.m_bus; - - mutex_lock(&mon_lock); - - if (mbus->nreaders <= 0) { - printk(KERN_ERR TAG ": consistency error on close\n"); - mutex_unlock(&mon_lock); - return 0; - } - mon_reader_del(mbus, &rp->r); - - mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE); - kfree(rp->b_vec); - kfree(rp); - - mutex_unlock(&mon_lock); - return 0; -} - -static ssize_t mon_bin_read(struct file *file, char __user *buf, - size_t nbytes, loff_t *ppos) -{ - struct mon_reader_bin *rp = file->private_data; - unsigned long flags; - struct mon_bin_hdr *ep; - unsigned int offset; - size_t step_len; - char *ptr; - ssize_t done = 0; - int rc; - - mutex_lock(&rp->fetch_lock); - - if ((rc = mon_bin_wait_event(file, rp)) < 0) { - mutex_unlock(&rp->fetch_lock); - return rc; - } - - ep = MON_OFF2HDR(rp, rp->b_out); - - if (rp->b_read < sizeof(struct mon_bin_hdr)) { - step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read); - ptr = ((char *)ep) + rp->b_read; - if (step_len && copy_to_user(buf, ptr, step_len)) { - mutex_unlock(&rp->fetch_lock); - return -EFAULT; - } - nbytes -= step_len; - buf += step_len; - rp->b_read += step_len; - done += step_len; - } - - if (rp->b_read >= sizeof(struct mon_bin_hdr)) { - step_len = min(nbytes, (size_t)ep->len_cap); - offset = rp->b_out + PKT_SIZE; - offset += rp->b_read - sizeof(struct mon_bin_hdr); - if (offset >= rp->b_size) - offset -= rp->b_size; - if (copy_from_buf(rp, offset, buf, step_len)) { - mutex_unlock(&rp->fetch_lock); - return -EFAULT; - } - nbytes -= step_len; - buf += step_len; - rp->b_read += step_len; - done += step_len; - } - - /* - * Check if whole packet was read, and if so, jump to the next one. - */ - if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) { - spin_lock_irqsave(&rp->b_lock, flags); - mon_buff_area_free(rp, PKT_SIZE + ep->len_cap); - spin_unlock_irqrestore(&rp->b_lock, flags); - rp->b_read = 0; - } - - mutex_unlock(&rp->fetch_lock); - return done; -} - -/* - * Remove at most nevents from chunked buffer. - * Returns the number of removed events. - */ -static int mon_bin_flush(struct mon_reader_bin *rp, unsigned nevents) -{ - unsigned long flags; - struct mon_bin_hdr *ep; - int i; - - mutex_lock(&rp->fetch_lock); - spin_lock_irqsave(&rp->b_lock, flags); - for (i = 0; i < nevents; ++i) { - if (MON_RING_EMPTY(rp)) - break; - - ep = MON_OFF2HDR(rp, rp->b_out); - mon_buff_area_free(rp, PKT_SIZE + ep->len_cap); - } - spin_unlock_irqrestore(&rp->b_lock, flags); - rp->b_read = 0; - mutex_unlock(&rp->fetch_lock); - return i; -} - -/* - * Fetch at most max event offsets into the buffer and put them into vec. - * The events are usually freed later with mon_bin_flush. - * Return the effective number of events fetched. - */ -static int mon_bin_fetch(struct file *file, struct mon_reader_bin *rp, - u32 __user *vec, unsigned int max) -{ - unsigned int cur_out; - unsigned int bytes, avail; - unsigned int size; - unsigned int nevents; - struct mon_bin_hdr *ep; - unsigned long flags; - int rc; - - mutex_lock(&rp->fetch_lock); - - if ((rc = mon_bin_wait_event(file, rp)) < 0) { - mutex_unlock(&rp->fetch_lock); - return rc; - } - - spin_lock_irqsave(&rp->b_lock, flags); - avail = rp->b_cnt; - spin_unlock_irqrestore(&rp->b_lock, flags); - - cur_out = rp->b_out; - nevents = 0; - bytes = 0; - while (bytes < avail) { - if (nevents >= max) - break; - - ep = MON_OFF2HDR(rp, cur_out); - if (put_user(cur_out, &vec[nevents])) { - mutex_unlock(&rp->fetch_lock); - return -EFAULT; - } - - nevents++; - size = ep->len_cap + PKT_SIZE; - size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1); - if ((cur_out += size) >= rp->b_size) - cur_out -= rp->b_size; - bytes += size; - } - - mutex_unlock(&rp->fetch_lock); - return nevents; -} - -/* - * Count events. This is almost the same as the above mon_bin_fetch, - * only we do not store offsets into user vector, and we have no limit. - */ -static int mon_bin_queued(struct mon_reader_bin *rp) -{ - unsigned int cur_out; - unsigned int bytes, avail; - unsigned int size; - unsigned int nevents; - struct mon_bin_hdr *ep; - unsigned long flags; - - mutex_lock(&rp->fetch_lock); - - spin_lock_irqsave(&rp->b_lock, flags); - avail = rp->b_cnt; - spin_unlock_irqrestore(&rp->b_lock, flags); - - cur_out = rp->b_out; - nevents = 0; - bytes = 0; - while (bytes < avail) { - ep = MON_OFF2HDR(rp, cur_out); - - nevents++; - size = ep->len_cap + PKT_SIZE; - size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1); - if ((cur_out += size) >= rp->b_size) - cur_out -= rp->b_size; - bytes += size; - } - - mutex_unlock(&rp->fetch_lock); - return nevents; -} - -/* - */ -static int mon_bin_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct mon_reader_bin *rp = file->private_data; - // struct mon_bus* mbus = rp->r.m_bus; - int ret = 0; - struct mon_bin_hdr *ep; - unsigned long flags; - - switch (cmd) { - - case MON_IOCQ_URB_LEN: - /* - * N.B. This only returns the size of data, without the header. - */ - spin_lock_irqsave(&rp->b_lock, flags); - if (!MON_RING_EMPTY(rp)) { - ep = MON_OFF2HDR(rp, rp->b_out); - ret = ep->len_cap; - } - spin_unlock_irqrestore(&rp->b_lock, flags); - break; - - case MON_IOCQ_RING_SIZE: - ret = rp->b_size; - break; - - case MON_IOCT_RING_SIZE: - /* - * Changing the buffer size will flush it's contents; the new - * buffer is allocated before releasing the old one to be sure - * the device will stay functional also in case of memory - * pressure. - */ - { - int size; - struct mon_pgmap *vec; - - if (arg < BUFF_MIN || arg > BUFF_MAX) - return -EINVAL; - - size = CHUNK_ALIGN(arg); - if ((vec = kzalloc(sizeof(struct mon_pgmap) * (size/CHUNK_SIZE), - GFP_KERNEL)) == NULL) { - ret = -ENOMEM; - break; - } - - ret = mon_alloc_buff(vec, size/CHUNK_SIZE); - if (ret < 0) { - kfree(vec); - break; - } - - mutex_lock(&rp->fetch_lock); - spin_lock_irqsave(&rp->b_lock, flags); - mon_free_buff(rp->b_vec, size/CHUNK_SIZE); - kfree(rp->b_vec); - rp->b_vec = vec; - rp->b_size = size; - rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0; - rp->cnt_lost = 0; - spin_unlock_irqrestore(&rp->b_lock, flags); - mutex_unlock(&rp->fetch_lock); - } - break; - - case MON_IOCH_MFLUSH: - ret = mon_bin_flush(rp, arg); - break; - - case MON_IOCX_GET: - { - struct mon_bin_get getb; - - if (copy_from_user(&getb, (void __user *)arg, - sizeof(struct mon_bin_get))) - return -EFAULT; - - if (getb.alloc > 0x10000000) /* Want to cast to u32 */ - return -EINVAL; - ret = mon_bin_get_event(file, rp, - getb.hdr, getb.data, (unsigned int)getb.alloc); - } - break; - -#ifdef CONFIG_COMPAT - case MON_IOCX_GET32: { - struct mon_bin_get32 getb; - - if (copy_from_user(&getb, (void __user *)arg, - sizeof(struct mon_bin_get32))) - return -EFAULT; - - ret = mon_bin_get_event(file, rp, - compat_ptr(getb.hdr32), compat_ptr(getb.data32), - getb.alloc32); - } - break; -#endif - - case MON_IOCX_MFETCH: - { - struct mon_bin_mfetch mfetch; - struct mon_bin_mfetch __user *uptr; - - uptr = (struct mon_bin_mfetch __user *)arg; - - if (copy_from_user(&mfetch, uptr, sizeof(mfetch))) - return -EFAULT; - - if (mfetch.nflush) { - ret = mon_bin_flush(rp, mfetch.nflush); - if (ret < 0) - return ret; - if (put_user(ret, &uptr->nflush)) - return -EFAULT; - } - ret = mon_bin_fetch(file, rp, mfetch.offvec, mfetch.nfetch); - if (ret < 0) - return ret; - if (put_user(ret, &uptr->nfetch)) - return -EFAULT; - ret = 0; - } - break; - -#ifdef CONFIG_COMPAT - case MON_IOCX_MFETCH32: - { - struct mon_bin_mfetch32 mfetch; - struct mon_bin_mfetch32 __user *uptr; - - uptr = (struct mon_bin_mfetch32 __user *) compat_ptr(arg); - - if (copy_from_user(&mfetch, uptr, sizeof(mfetch))) - return -EFAULT; - - if (mfetch.nflush32) { - ret = mon_bin_flush(rp, mfetch.nflush32); - if (ret < 0) - return ret; - if (put_user(ret, &uptr->nflush32)) - return -EFAULT; - } - ret = mon_bin_fetch(file, rp, compat_ptr(mfetch.offvec32), - mfetch.nfetch32); - if (ret < 0) - return ret; - if (put_user(ret, &uptr->nfetch32)) - return -EFAULT; - ret = 0; - } - break; -#endif - - case MON_IOCG_STATS: { - struct mon_bin_stats __user *sp; - unsigned int nevents; - unsigned int ndropped; - - spin_lock_irqsave(&rp->b_lock, flags); - ndropped = rp->cnt_lost; - rp->cnt_lost = 0; - spin_unlock_irqrestore(&rp->b_lock, flags); - nevents = mon_bin_queued(rp); - - sp = (struct mon_bin_stats __user *)arg; - if (put_user(rp->cnt_lost, &sp->dropped)) - return -EFAULT; - if (put_user(nevents, &sp->queued)) - return -EFAULT; - - } - break; - - default: - return -ENOTTY; - } - - return ret; -} - -static unsigned int -mon_bin_poll(struct file *file, struct poll_table_struct *wait) -{ - struct mon_reader_bin *rp = file->private_data; - unsigned int mask = 0; - unsigned long flags; - - if (file->f_mode & FMODE_READ) - poll_wait(file, &rp->b_wait, wait); - - spin_lock_irqsave(&rp->b_lock, flags); - if (!MON_RING_EMPTY(rp)) - mask |= POLLIN | POLLRDNORM; /* readable */ - spin_unlock_irqrestore(&rp->b_lock, flags); - return mask; -} - -/* - * open and close: just keep track of how many times the device is - * mapped, to use the proper memory allocation function. - */ -static void mon_bin_vma_open(struct vm_area_struct *vma) -{ - struct mon_reader_bin *rp = vma->vm_private_data; - rp->mmap_active++; -} - -static void mon_bin_vma_close(struct vm_area_struct *vma) -{ - struct mon_reader_bin *rp = vma->vm_private_data; - rp->mmap_active--; -} - -/* - * Map ring pages to user space. - */ -struct page *mon_bin_vma_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) -{ - struct mon_reader_bin *rp = vma->vm_private_data; - unsigned long offset, chunk_idx; - struct page *pageptr; - - offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); - if (offset >= rp->b_size) - return NOPAGE_SIGBUS; - chunk_idx = offset / CHUNK_SIZE; - pageptr = rp->b_vec[chunk_idx].pg; - get_page(pageptr); - if (type) - *type = VM_FAULT_MINOR; - return pageptr; -} - -struct vm_operations_struct mon_bin_vm_ops = { - .open = mon_bin_vma_open, - .close = mon_bin_vma_close, - .nopage = mon_bin_vma_nopage, -}; - -int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma) -{ - /* don't do anything here: "nopage" will set up page table entries */ - vma->vm_ops = &mon_bin_vm_ops; - vma->vm_flags |= VM_RESERVED; - vma->vm_private_data = filp->private_data; - mon_bin_vma_open(vma); - return 0; -} - -struct file_operations mon_fops_binary = { - .owner = THIS_MODULE, - .open = mon_bin_open, - .llseek = no_llseek, - .read = mon_bin_read, - /* .write = mon_text_write, */ - .poll = mon_bin_poll, - .ioctl = mon_bin_ioctl, - .release = mon_bin_release, -}; - -static int mon_bin_wait_event(struct file *file, struct mon_reader_bin *rp) -{ - DECLARE_WAITQUEUE(waita, current); - unsigned long flags; - - add_wait_queue(&rp->b_wait, &waita); - set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irqsave(&rp->b_lock, flags); - while (MON_RING_EMPTY(rp)) { - spin_unlock_irqrestore(&rp->b_lock, flags); - - if (file->f_flags & O_NONBLOCK) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&rp->b_wait, &waita); - return -EWOULDBLOCK; /* Same as EAGAIN in Linux */ - } - schedule(); - if (signal_pending(current)) { - remove_wait_queue(&rp->b_wait, &waita); - return -EINTR; - } - set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irqsave(&rp->b_lock, flags); - } - spin_unlock_irqrestore(&rp->b_lock, flags); - - set_current_state(TASK_RUNNING); - remove_wait_queue(&rp->b_wait, &waita); - return 0; -} - -static int mon_alloc_buff(struct mon_pgmap *map, int npages) -{ - int n; - unsigned long vaddr; - - for (n = 0; n < npages; n++) { - vaddr = get_zeroed_page(GFP_KERNEL); - if (vaddr == 0) { - while (n-- != 0) - free_page((unsigned long) map[n].ptr); - return -ENOMEM; - } - map[n].ptr = (unsigned char *) vaddr; - map[n].pg = virt_to_page(vaddr); - } - return 0; -} - -static void mon_free_buff(struct mon_pgmap *map, int npages) -{ - int n; - - for (n = 0; n < npages; n++) - free_page((unsigned long) map[n].ptr); -} - -int __init mon_bin_init(void) -{ - int rc; - - rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon"); - if (rc < 0) - goto err_dev; - - cdev_init(&mon_bin_cdev, &mon_fops_binary); - mon_bin_cdev.owner = THIS_MODULE; - - rc = cdev_add(&mon_bin_cdev, mon_bin_dev0, MON_BIN_MAX_MINOR); - if (rc < 0) - goto err_add; - - return 0; - -err_add: - unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); -err_dev: - return rc; -} - -void __exit mon_bin_exit(void) -{ - cdev_del(&mon_bin_cdev); - unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); -} diff --git a/trunk/drivers/usb/mon/mon_dma.c b/trunk/drivers/usb/mon/mon_dma.c index 140cc80bd2b1..ddcfc01e77a0 100644 --- a/trunk/drivers/usb/mon/mon_dma.c +++ b/trunk/drivers/usb/mon/mon_dma.c @@ -48,36 +48,6 @@ char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len) local_irq_restore(flags); return 0; } - -void mon_dmapeek_vec(const struct mon_reader_bin *rp, - unsigned int offset, dma_addr_t dma_addr, unsigned int length) -{ - unsigned long flags; - unsigned int step_len; - struct page *pg; - unsigned char *map; - unsigned long page_off, page_len; - - local_irq_save(flags); - while (length) { - /* compute number of bytes we are going to copy in this page */ - step_len = length; - page_off = dma_addr & (PAGE_SIZE-1); - page_len = PAGE_SIZE - page_off; - if (page_len < step_len) - step_len = page_len; - - /* copy data and advance pointers */ - pg = phys_to_page(dma_addr); - map = kmap_atomic(pg, KM_IRQ0); - offset = mon_copy_to_buff(rp, offset, map + page_off, step_len); - kunmap_atomic(map, KM_IRQ0); - dma_addr += step_len; - length -= step_len; - } - local_irq_restore(flags); -} - #endif /* __i386__ */ #ifndef MON_HAS_UNMAP @@ -85,11 +55,4 @@ char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len) { return 'D'; } - -void mon_dmapeek_vec(const struct mon_reader_bin *rp, - unsigned int offset, dma_addr_t dma_addr, unsigned int length) -{ - ; -} - -#endif /* MON_HAS_UNMAP */ +#endif diff --git a/trunk/drivers/usb/mon/mon_main.c b/trunk/drivers/usb/mon/mon_main.c index c9739e7b35e5..394bbf2f68d4 100644 --- a/trunk/drivers/usb/mon/mon_main.c +++ b/trunk/drivers/usb/mon/mon_main.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -21,10 +22,11 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb); static void mon_stop(struct mon_bus *mbus); static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus); static void mon_bus_drop(struct kref *r); -static void mon_bus_init(struct usb_bus *ubus); +static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus); DEFINE_MUTEX(mon_lock); +static struct dentry *mon_dir; /* /dbg/usbmon */ static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */ /* @@ -198,7 +200,7 @@ static void mon_stop(struct mon_bus *mbus) */ static void mon_bus_add(struct usb_bus *ubus) { - mon_bus_init(ubus); + mon_bus_init(mon_dir, ubus); } /* @@ -210,8 +212,8 @@ static void mon_bus_remove(struct usb_bus *ubus) mutex_lock(&mon_lock); list_del(&mbus->bus_link); - if (mbus->text_inited) - mon_text_del(mbus); + debugfs_remove(mbus->dent_t); + debugfs_remove(mbus->dent_s); mon_dissolve(mbus, ubus); kref_put(&mbus->ref, mon_bus_drop); @@ -279,9 +281,13 @@ static void mon_bus_drop(struct kref *r) * - refcount USB bus struct * - link */ -static void mon_bus_init(struct usb_bus *ubus) +static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus) { + struct dentry *d; struct mon_bus *mbus; + enum { NAMESZ = 10 }; + char name[NAMESZ]; + int rc; if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL) goto err_alloc; @@ -297,54 +303,57 @@ static void mon_bus_init(struct usb_bus *ubus) ubus->mon_bus = mbus; mbus->uses_dma = ubus->uses_dma; - mbus->text_inited = mon_text_add(mbus, ubus); - // mon_bin_add(...) + rc = snprintf(name, NAMESZ, "%dt", ubus->busnum); + if (rc <= 0 || rc >= NAMESZ) + goto err_print_t; + d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_text); + if (d == NULL) + goto err_create_t; + mbus->dent_t = d; + + rc = snprintf(name, NAMESZ, "%ds", ubus->busnum); + if (rc <= 0 || rc >= NAMESZ) + goto err_print_s; + d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_stat); + if (d == NULL) + goto err_create_s; + mbus->dent_s = d; mutex_lock(&mon_lock); list_add_tail(&mbus->bus_link, &mon_buses); mutex_unlock(&mon_lock); return; +err_create_s: +err_print_s: + debugfs_remove(mbus->dent_t); +err_create_t: +err_print_t: + kfree(mbus); err_alloc: return; } -/* - * Search a USB bus by number. Notice that USB bus numbers start from one, - * which we may later use to identify "all" with zero. - * - * This function must be called with mon_lock held. - * - * This is obviously inefficient and may be revised in the future. - */ -struct mon_bus *mon_bus_lookup(unsigned int num) -{ - struct list_head *p; - struct mon_bus *mbus; - - list_for_each (p, &mon_buses) { - mbus = list_entry(p, struct mon_bus, bus_link); - if (mbus->u_bus->busnum == num) { - return mbus; - } - } - return NULL; -} - static int __init mon_init(void) { struct usb_bus *ubus; - int rc; + struct dentry *mondir; - if ((rc = mon_text_init()) != 0) - goto err_text; - if ((rc = mon_bin_init()) != 0) - goto err_bin; + mondir = debugfs_create_dir("usbmon", NULL); + if (IS_ERR(mondir)) { + printk(KERN_NOTICE TAG ": debugfs is not available\n"); + return -ENODEV; + } + if (mondir == NULL) { + printk(KERN_NOTICE TAG ": unable to create usbmon directory\n"); + return -ENODEV; + } + mon_dir = mondir; if (usb_mon_register(&mon_ops_0) != 0) { printk(KERN_NOTICE TAG ": unable to register with the core\n"); - rc = -ENODEV; - goto err_reg; + debugfs_remove(mondir); + return -ENODEV; } // MOD_INC_USE_COUNT(which_module?); @@ -352,17 +361,10 @@ static int __init mon_init(void) mutex_lock(&usb_bus_list_lock); list_for_each_entry (ubus, &usb_bus_list, bus_list) { - mon_bus_init(ubus); + mon_bus_init(mondir, ubus); } mutex_unlock(&usb_bus_list_lock); return 0; - -err_reg: - mon_bin_exit(); -err_bin: - mon_text_exit(); -err_text: - return rc; } static void __exit mon_exit(void) @@ -379,8 +381,8 @@ static void __exit mon_exit(void) mbus = list_entry(p, struct mon_bus, bus_link); list_del(p); - if (mbus->text_inited) - mon_text_del(mbus); + debugfs_remove(mbus->dent_t); + debugfs_remove(mbus->dent_s); /* * This never happens, because the open/close paths in @@ -399,8 +401,7 @@ static void __exit mon_exit(void) } mutex_unlock(&mon_lock); - mon_text_exit(); - mon_bin_exit(); + debugfs_remove(mon_dir); } module_init(mon_init); diff --git a/trunk/drivers/usb/mon/mon_text.c b/trunk/drivers/usb/mon/mon_text.c index d38a1279d9d9..05cf2c9a8f84 100644 --- a/trunk/drivers/usb/mon/mon_text.c +++ b/trunk/drivers/usb/mon/mon_text.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include "usb_mon.h" @@ -64,8 +63,6 @@ struct mon_reader_text { char slab_name[SLAB_NAME_SZ]; }; -static struct dentry *mon_dir; /* Usually /sys/kernel/debug/usbmon */ - static void mon_text_ctor(void *, struct kmem_cache *, unsigned long); /* @@ -439,7 +436,7 @@ static int mon_text_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations mon_fops_text = { +const struct file_operations mon_fops_text = { .owner = THIS_MODULE, .open = mon_text_open, .llseek = no_llseek, @@ -450,47 +447,6 @@ static const struct file_operations mon_fops_text = { .release = mon_text_release, }; -int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus) -{ - struct dentry *d; - enum { NAMESZ = 10 }; - char name[NAMESZ]; - int rc; - - rc = snprintf(name, NAMESZ, "%dt", ubus->busnum); - if (rc <= 0 || rc >= NAMESZ) - goto err_print_t; - d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text); - if (d == NULL) - goto err_create_t; - mbus->dent_t = d; - - /* XXX The stats do not belong to here (text API), but oh well... */ - rc = snprintf(name, NAMESZ, "%ds", ubus->busnum); - if (rc <= 0 || rc >= NAMESZ) - goto err_print_s; - d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_stat); - if (d == NULL) - goto err_create_s; - mbus->dent_s = d; - - return 1; - -err_create_s: -err_print_s: - debugfs_remove(mbus->dent_t); - mbus->dent_t = NULL; -err_create_t: -err_print_t: - return 0; -} - -void mon_text_del(struct mon_bus *mbus) -{ - debugfs_remove(mbus->dent_t); - debugfs_remove(mbus->dent_s); -} - /* * Slab interface: constructor. */ @@ -503,24 +459,3 @@ static void mon_text_ctor(void *mem, struct kmem_cache *slab, unsigned long sfla memset(mem, 0xe5, sizeof(struct mon_event_text)); } -int __init mon_text_init(void) -{ - struct dentry *mondir; - - mondir = debugfs_create_dir("usbmon", NULL); - if (IS_ERR(mondir)) { - printk(KERN_NOTICE TAG ": debugfs is not available\n"); - return -ENODEV; - } - if (mondir == NULL) { - printk(KERN_NOTICE TAG ": unable to create usbmon directory\n"); - return -ENODEV; - } - mon_dir = mondir; - return 0; -} - -void __exit mon_text_exit(void) -{ - debugfs_remove(mon_dir); -} diff --git a/trunk/drivers/usb/mon/usb_mon.h b/trunk/drivers/usb/mon/usb_mon.h index 4f949ce8a7f3..ab9d02d5df77 100644 --- a/trunk/drivers/usb/mon/usb_mon.h +++ b/trunk/drivers/usb/mon/usb_mon.h @@ -17,11 +17,9 @@ struct mon_bus { struct list_head bus_link; spinlock_t lock; - struct usb_bus *u_bus; - - int text_inited; struct dentry *dent_s; /* Debugging file */ struct dentry *dent_t; /* Text interface file */ + struct usb_bus *u_bus; int uses_dma; /* Ref */ @@ -50,35 +48,13 @@ struct mon_reader { void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r); void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r); -struct mon_bus *mon_bus_lookup(unsigned int num); - -int /*bool*/ mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus); -void mon_text_del(struct mon_bus *mbus); -// void mon_bin_add(struct mon_bus *); - -int __init mon_text_init(void); -void __exit mon_text_exit(void); -int __init mon_bin_init(void); -void __exit mon_bin_exit(void); - /* - * DMA interface. - * - * XXX The vectored side needs a serious re-thinking. Abstracting vectors, - * like in Paolo's original patch, produces a double pkmap. We need an idea. -*/ + */ extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len); -struct mon_reader_bin; -extern void mon_dmapeek_vec(const struct mon_reader_bin *rp, - unsigned int offset, dma_addr_t dma_addr, unsigned int len); -extern unsigned int mon_copy_to_buff(const struct mon_reader_bin *rp, - unsigned int offset, const unsigned char *from, unsigned int len); - -/* - */ extern struct mutex mon_lock; +extern const struct file_operations mon_fops_text; extern const struct file_operations mon_fops_stat; #endif /* __USB_MON_H */ diff --git a/trunk/drivers/usb/net/Kconfig b/trunk/drivers/usb/net/Kconfig index a2b94ef512bc..e081836014ac 100644 --- a/trunk/drivers/usb/net/Kconfig +++ b/trunk/drivers/usb/net/Kconfig @@ -222,15 +222,13 @@ config USB_NET_MCS7830 adapters marketed under the DeLOCK brand. config USB_NET_RNDIS_HOST - tristate "Host for RNDIS and ActiveSync devices (EXPERIMENTAL)" + tristate "Host for RNDIS devices (EXPERIMENTAL)" depends on USB_USBNET && EXPERIMENTAL select USB_NET_CDCETHER help This option enables hosting "Remote NDIS" USB networking links, as encouraged by Microsoft (instead of CDC Ethernet!) for use in - various devices that may only support this protocol. A variant - of this protocol (with even less public documentation) seems to - be at the root of Microsoft's "ActiveSync" too. + various devices that may only support this protocol. Avoid using this protocol unless you have no better options. The protocol specification is incomplete, and is controlled by diff --git a/trunk/drivers/usb/net/asix.c b/trunk/drivers/usb/net/asix.c index 4206df2d61b7..896449f0cf85 100644 --- a/trunk/drivers/usb/net/asix.c +++ b/trunk/drivers/usb/net/asix.c @@ -1449,10 +1449,6 @@ static const struct usb_device_id products [] = { // Linksys USB1000 USB_DEVICE (0x1737, 0x0039), .driver_info = (unsigned long) &ax88178_info, -}, { - // IO-DATA ETG-US2 - USB_DEVICE (0x04bb, 0x0930), - .driver_info = (unsigned long) &ax88178_info, }, { }, // END }; diff --git a/trunk/drivers/usb/net/cdc_ether.c b/trunk/drivers/usb/net/cdc_ether.c index e5cdafa258dd..44a91547146e 100644 --- a/trunk/drivers/usb/net/cdc_ether.c +++ b/trunk/drivers/usb/net/cdc_ether.c @@ -1,7 +1,6 @@ /* * CDC Ethernet based networking peripherals * Copyright (C) 2003-2005 by David Brownell - * Copyright (C) 2006 by Ole Andre Vadla Ravnas (ActiveSync) * * 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 @@ -36,29 +35,6 @@ #include "usbnet.h" -#if defined(CONFIG_USB_NET_RNDIS_HOST) || defined(CONFIG_USB_NET_RNDIS_HOST_MODULE) - -static int is_rndis(struct usb_interface_descriptor *desc) -{ - return desc->bInterfaceClass == USB_CLASS_COMM - && desc->bInterfaceSubClass == 2 - && desc->bInterfaceProtocol == 0xff; -} - -static int is_activesync(struct usb_interface_descriptor *desc) -{ - return desc->bInterfaceClass == USB_CLASS_MISC - && desc->bInterfaceSubClass == 1 - && desc->bInterfaceProtocol == 1; -} - -#else - -#define is_rndis(desc) 0 -#define is_activesync(desc) 0 - -#endif - /* * probes control interface, claims data interface, collects the bulk * endpoints, activates data interface (if needed), maybe sets MTU. @@ -95,8 +71,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) /* this assumes that if there's a non-RNDIS vendor variant * of cdc-acm, it'll fail RNDIS requests cleanly. */ - rndis = is_rndis(&intf->cur_altsetting->desc) - || is_activesync(&intf->cur_altsetting->desc); + rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff); memset(info, 0, sizeof *info); info->control = intf; @@ -124,23 +99,6 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) goto bad_desc; } break; - case USB_CDC_ACM_TYPE: - /* paranoia: disambiguate a "real" vendor-specific - * modem interface from an RNDIS non-modem. - */ - if (rndis) { - struct usb_cdc_acm_descriptor *d; - - d = (void *) buf; - if (d->bmCapabilities) { - dev_dbg(&intf->dev, - "ACM capabilities %02x, " - "not really RNDIS?\n", - d->bmCapabilities); - goto bad_desc; - } - } - break; case USB_CDC_UNION_TYPE: if (info->u) { dev_dbg(&intf->dev, "extra CDC union\n"); @@ -213,21 +171,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) buf += buf [0]; } - /* Microsoft ActiveSync based RNDIS devices lack the CDC descriptors, - * so we'll hard-wire the interfaces and not check for descriptors. - */ - if (is_activesync(&intf->cur_altsetting->desc) && !info->u) { - info->control = usb_ifnum_to_if(dev->udev, 0); - info->data = usb_ifnum_to_if(dev->udev, 1); - if (!info->control || !info->data) { - dev_dbg(&intf->dev, - "activesync: master #0/%p slave #1/%p\n", - info->control, - info->data); - goto bad_desc; - } - - } else if (!info->header || !info->u || (!rndis && !info->ether)) { + if (!info->header || !info->u || (!rndis && !info->ether)) { dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n", info->header ? "" : "header ", info->u ? "" : "union ", diff --git a/trunk/drivers/usb/net/kaweth.c b/trunk/drivers/usb/net/kaweth.c index 36a989160a68..fa78326d0bf0 100644 --- a/trunk/drivers/usb/net/kaweth.c +++ b/trunk/drivers/usb/net/kaweth.c @@ -179,7 +179,6 @@ static struct usb_driver kaweth_driver = { .suspend = kaweth_suspend, .resume = kaweth_resume, .id_table = usb_klsi_table, - .supports_autosuspend = 1, }; typedef __u8 eth_addr_t[6]; @@ -226,7 +225,6 @@ struct kaweth_device struct delayed_work lowmem_work; struct usb_device *dev; - struct usb_interface *intf; struct net_device *net; wait_queue_head_t term_wait; @@ -664,14 +662,9 @@ static int kaweth_open(struct net_device *net) dbg("Opening network device."); - res = usb_autopm_get_interface(kaweth->intf); - if (res) { - err("Interface cannot be resumed."); - return -EIO; - } res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL); if (res) - goto err_out; + return -EIO; usb_fill_int_urb( kaweth->irq_urb, @@ -688,7 +681,7 @@ static int kaweth_open(struct net_device *net) res = usb_submit_urb(kaweth->irq_urb, GFP_KERNEL); if (res) { usb_kill_urb(kaweth->rx_urb); - goto err_out; + return -EIO; } kaweth->opened = 1; @@ -696,14 +689,10 @@ static int kaweth_open(struct net_device *net) kaweth_async_set_rx_mode(kaweth); return 0; - -err_out: - usb_autopm_enable(kaweth->intf); - return -EIO; } /**************************************************************** - * kaweth_kill_urbs + * kaweth_close ****************************************************************/ static void kaweth_kill_urbs(struct kaweth_device *kaweth) { @@ -735,29 +724,17 @@ static int kaweth_close(struct net_device *net) kaweth->status &= ~KAWETH_STATUS_CLOSING; - usb_autopm_enable(kaweth->intf); - return 0; } static void kaweth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct kaweth_device *kaweth = netdev_priv(dev); strlcpy(info->driver, driver_name, sizeof(info->driver)); - usb_make_path(kaweth->dev, info->bus_info, sizeof (info->bus_info)); -} - -static u32 kaweth_get_link(struct net_device *dev) -{ - struct kaweth_device *kaweth = netdev_priv(dev); - - return kaweth->linkstate; } static struct ethtool_ops ops = { - .get_drvinfo = kaweth_get_drvinfo, - .get_link = kaweth_get_link + .get_drvinfo = kaweth_get_drvinfo }; /**************************************************************** @@ -931,7 +908,6 @@ static int kaweth_suspend(struct usb_interface *intf, pm_message_t message) struct kaweth_device *kaweth = usb_get_intfdata(intf); unsigned long flags; - dbg("Suspending device"); spin_lock_irqsave(&kaweth->device_lock, flags); kaweth->status |= KAWETH_STATUS_SUSPENDING; spin_unlock_irqrestore(&kaweth->device_lock, flags); @@ -948,7 +924,6 @@ static int kaweth_resume(struct usb_interface *intf) struct kaweth_device *kaweth = usb_get_intfdata(intf); unsigned long flags; - dbg("Resuming device"); spin_lock_irqsave(&kaweth->device_lock, flags); kaweth->status &= ~KAWETH_STATUS_SUSPENDING; spin_unlock_irqrestore(&kaweth->device_lock, flags); @@ -1111,8 +1086,6 @@ static int kaweth_probe( dbg("Initializing net device."); - kaweth->intf = intf; - kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->tx_urb) goto err_free_netdev; @@ -1292,7 +1265,7 @@ static int kaweth_internal_control_msg(struct usb_device *usb_dev, { struct urb *urb; int retv; - int length = 0; /* shut up GCC */ + int length; urb = usb_alloc_urb(0, GFP_NOIO); if (!urb) diff --git a/trunk/drivers/usb/net/pegasus.h b/trunk/drivers/usb/net/pegasus.h index c7467823cd1c..98f6898cae1f 100644 --- a/trunk/drivers/usb/net/pegasus.h +++ b/trunk/drivers/usb/net/pegasus.h @@ -214,9 +214,9 @@ PEGASUS_DEV( "Billionton USBEL-100", VENDOR_BILLIONTON, 0x0988, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511, DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Corega FEther USB-TX", VENDOR_COREGA, 0x0004, +PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004, DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "Corega FEther USB-TXS", VENDOR_COREGA, 0x000d, +PEGASUS_DEV( "Corega FEter USB-TXS", VENDOR_COREGA, 0x000d, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001, DEFAULT_GPIO_RESET ) diff --git a/trunk/drivers/usb/net/rndis_host.c b/trunk/drivers/usb/net/rndis_host.c index be888d2d813c..a322a16d9cf8 100644 --- a/trunk/drivers/usb/net/rndis_host.c +++ b/trunk/drivers/usb/net/rndis_host.c @@ -49,8 +49,6 @@ * - In some cases, MS-Windows will emit undocumented requests; this * matters more to peripheral implementations than host ones. * - * Moreover there's a no-open-specs variant of RNDIS called "ActiveSync". - * * For these reasons and others, ** USE OF RNDIS IS STRONGLY DISCOURAGED ** in * favor of such non-proprietary alternatives as CDC Ethernet or the newer (and * currently rare) "Ethernet Emulation Model" (EEM). @@ -63,9 +61,6 @@ * - control-in: GET_ENCAPSULATED * * We'll try to ignore the RESPONSE_AVAILABLE notifications. - * - * REVISIT some RNDIS implementations seem to have curious issues still - * to be resolved. */ struct rndis_msg_hdr { __le32 msg_type; /* RNDIS_MSG_* */ @@ -76,14 +71,8 @@ struct rndis_msg_hdr { // ... and more } __attribute__ ((packed)); -/* MS-Windows uses this strange size, but RNDIS spec says 1024 minimum */ -#define CONTROL_BUFFER_SIZE 1025 - -/* RNDIS defines an (absurdly huge) 10 second control timeout, - * but ActiveSync seems to use a more usual 5 second timeout - * (which matches the USB 2.0 spec). - */ -#define RNDIS_CONTROL_TIMEOUT_MS (5 * 1000) +/* RNDIS defines this (absurdly huge) control timeout */ +#define RNDIS_CONTROL_TIMEOUT_MS (10 * 1000) #define ccpu2 __constant_cpu_to_le32 @@ -281,7 +270,6 @@ static void rndis_status(struct usbnet *dev, struct urb *urb) static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) { struct cdc_state *info = (void *) &dev->data; - int master_ifnum; int retval; unsigned count; __le32 rsp; @@ -291,7 +279,7 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) * disconnect(): either serialize, or dispatch responses on xid */ - /* Issue the request; xid is unique, don't bother byteswapping it */ + /* Issue the request; don't bother byteswapping our xid */ if (likely(buf->msg_type != RNDIS_MSG_HALT && buf->msg_type != RNDIS_MSG_RESET)) { xid = dev->xid++; @@ -299,12 +287,11 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) xid = dev->xid++; buf->request_id = (__force __le32) xid; } - master_ifnum = info->control->cur_altsetting->desc.bInterfaceNumber; retval = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), USB_CDC_SEND_ENCAPSULATED_COMMAND, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, master_ifnum, + 0, info->u->bMasterInterface0, buf, le32_to_cpu(buf->msg_len), RNDIS_CONTROL_TIMEOUT_MS); if (unlikely(retval < 0 || xid == 0)) @@ -319,13 +306,13 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) */ rsp = buf->msg_type | RNDIS_MSG_COMPLETION; for (count = 0; count < 10; count++) { - memset(buf, 0, CONTROL_BUFFER_SIZE); + memset(buf, 0, 1024); retval = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), USB_CDC_GET_ENCAPSULATED_RESPONSE, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, master_ifnum, - buf, CONTROL_BUFFER_SIZE, + 0, info->u->bMasterInterface0, + buf, 1024, RNDIS_CONTROL_TIMEOUT_MS); if (likely(retval >= 8)) { msg_len = le32_to_cpu(buf->msg_len); @@ -363,7 +350,7 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) usb_sndctrlpipe(dev->udev, 0), USB_CDC_SEND_ENCAPSULATED_COMMAND, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, master_ifnum, + 0, info->u->bMasterInterface0, msg, sizeof *msg, RNDIS_CONTROL_TIMEOUT_MS); if (unlikely(retval < 0)) @@ -406,64 +393,38 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) u32 tmp; /* we can't rely on i/o from stack working, or stack allocation */ - u.buf = kmalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL); + u.buf = kmalloc(1024, GFP_KERNEL); if (!u.buf) return -ENOMEM; retval = usbnet_generic_cdc_bind(dev, intf); if (retval < 0) goto fail; + net->hard_header_len += sizeof (struct rndis_data_hdr); + + /* initialize; max transfer is 16KB at full speed */ u.init->msg_type = RNDIS_MSG_INIT; u.init->msg_len = ccpu2(sizeof *u.init); u.init->major_version = ccpu2(1); u.init->minor_version = ccpu2(0); + u.init->max_transfer_size = ccpu2(net->mtu + net->hard_header_len); - /* max transfer (in spec) is 0x4000 at full speed, but for - * TX we'll stick to one Ethernet packet plus RNDIS framing. - * For RX we handle drivers that zero-pad to end-of-packet. - * Don't let userspace change these settings. - */ - net->hard_header_len += sizeof (struct rndis_data_hdr); - dev->hard_mtu = net->mtu + net->hard_header_len; - - dev->rx_urb_size = dev->hard_mtu + (dev->maxpacket + 1); - dev->rx_urb_size &= ~(dev->maxpacket - 1); - u.init->max_transfer_size = cpu_to_le32(dev->rx_urb_size); - - net->change_mtu = NULL; retval = rndis_command(dev, u.header); if (unlikely(retval < 0)) { /* it might not even be an RNDIS device!! */ dev_err(&intf->dev, "RNDIS init failed, %d\n", retval); - goto fail_and_release; - } - tmp = le32_to_cpu(u.init_c->max_transfer_size); - if (tmp < dev->hard_mtu) { - dev_err(&intf->dev, - "dev can't take %u byte packets (max %u)\n", - dev->hard_mtu, tmp); goto fail_and_release; } - + dev->hard_mtu = le32_to_cpu(u.init_c->max_transfer_size); /* REVISIT: peripheral "alignment" request is ignored ... */ - dev_dbg(&intf->dev, - "hard mtu %u (%u from dev), rx buflen %Zu, align %d\n", - dev->hard_mtu, tmp, dev->rx_urb_size, + dev_dbg(&intf->dev, "hard mtu %u, align %d\n", dev->hard_mtu, 1 << le32_to_cpu(u.init_c->packet_alignment)); - /* Get designated host ethernet address. - * - * Adding a payload exactly the same size as the expected response - * payload is an evident requirement MSFT added for ActiveSync. - * This undocumented (and nonsensical) issue was found by sniffing - * protocol requests from the ActiveSync 4.1 Windows driver. - */ - memset(u.get, 0, sizeof *u.get + 48); + /* get designated host ethernet address */ + memset(u.get, 0, sizeof *u.get); u.get->msg_type = RNDIS_MSG_QUERY; - u.get->msg_len = ccpu2(sizeof *u.get + 48); + u.get->msg_len = ccpu2(sizeof *u.get); u.get->oid = OID_802_3_PERMANENT_ADDRESS; - u.get->len = ccpu2(48); - u.get->offset = ccpu2(20); retval = rndis_command(dev, u.header); if (unlikely(retval < 0)) { @@ -471,7 +432,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) goto fail_and_release; } tmp = le32_to_cpu(u.get_c->offset); - if (unlikely((tmp + 8) > (CONTROL_BUFFER_SIZE - ETH_ALEN) + if (unlikely((tmp + 8) > (1024 - ETH_ALEN) || u.get_c->len != ccpu2(ETH_ALEN))) { dev_err(&intf->dev, "rndis ethaddr off %d len %d ?\n", tmp, le32_to_cpu(u.get_c->len)); @@ -637,10 +598,6 @@ static const struct usb_device_id products [] = { /* RNDIS is MSFT's un-official variant of CDC ACM */ USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), .driver_info = (unsigned long) &rndis_info, -}, { - /* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */ - USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1), - .driver_info = (unsigned long) &rndis_info, }, { }, // END }; diff --git a/trunk/drivers/usb/serial/aircable.c b/trunk/drivers/usb/serial/aircable.c index 11dad42c3c60..86bcf63b6ba5 100644 --- a/trunk/drivers/usb/serial/aircable.c +++ b/trunk/drivers/usb/serial/aircable.c @@ -572,20 +572,8 @@ static void aircable_unthrottle(struct usb_serial_port *port) schedule_work(&priv->rx_work); } -static struct usb_driver aircable_driver = { - .name = "aircable", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, - .no_dynamic_id = 1, -}; - static struct usb_serial_driver aircable_device = { - .driver = { - .owner = THIS_MODULE, - .name = "aircable", - }, - .usb_driver = &aircable_driver, + .description = "aircable", .id_table = id_table, .num_ports = 1, .attach = aircable_attach, @@ -599,6 +587,13 @@ static struct usb_serial_driver aircable_device = { .unthrottle = aircable_unthrottle, }; +static struct usb_driver aircable_driver = { + .name = "aircable", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, +}; + static int __init aircable_init (void) { int retval; diff --git a/trunk/drivers/usb/serial/airprime.c b/trunk/drivers/usb/serial/airprime.c index 0af42e32fa0a..f2ca76a9cbac 100644 --- a/trunk/drivers/usb/serial/airprime.c +++ b/trunk/drivers/usb/serial/airprime.c @@ -277,7 +277,6 @@ static struct usb_serial_driver airprime_device = { .owner = THIS_MODULE, .name = "airprime", }, - .usb_driver = &airprime_driver, .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, diff --git a/trunk/drivers/usb/serial/ark3116.c b/trunk/drivers/usb/serial/ark3116.c index edd685791a6b..5261cd22ee6b 100644 --- a/trunk/drivers/usb/serial/ark3116.c +++ b/trunk/drivers/usb/serial/ark3116.c @@ -444,7 +444,6 @@ static struct usb_driver ark3116_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 1, }; static struct usb_serial_driver ark3116_device = { @@ -453,7 +452,6 @@ static struct usb_serial_driver ark3116_device = { .name = "ark3116", }, .id_table = id_table, - .usb_driver = &ark3116_driver, .num_interrupt_in = 1, .num_bulk_in = 1, .num_bulk_out = 1, diff --git a/trunk/drivers/usb/serial/belkin_sa.c b/trunk/drivers/usb/serial/belkin_sa.c index 3b800d277c4b..38b4dae319ee 100644 --- a/trunk/drivers/usb/serial/belkin_sa.c +++ b/trunk/drivers/usb/serial/belkin_sa.c @@ -126,7 +126,6 @@ static struct usb_serial_driver belkin_device = { .name = "belkin", }, .description = "Belkin / Peracom / GoHubs USB Serial Adapter", - .usb_driver = &belkin_driver, .id_table = id_table_combined, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/trunk/drivers/usb/serial/bus.c b/trunk/drivers/usb/serial/bus.c index c08a38402b93..6542f220468f 100644 --- a/trunk/drivers/usb/serial/bus.c +++ b/trunk/drivers/usb/serial/bus.c @@ -103,52 +103,11 @@ static int usb_serial_device_remove (struct device *dev) return retval; } -#ifdef CONFIG_HOTPLUG -static ssize_t store_new_id(struct device_driver *driver, - const char *buf, size_t count) -{ - struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver); - ssize_t retval = usb_store_new_id(&usb_drv->dynids, driver, buf, count); - - if (retval >= 0 && usb_drv->usb_driver != NULL) - retval = usb_store_new_id(&usb_drv->usb_driver->dynids, - &usb_drv->usb_driver->drvwrap.driver, - buf, count); - return retval; -} - -static struct driver_attribute drv_attrs[] = { - __ATTR(new_id, S_IWUSR, NULL, store_new_id), - __ATTR_NULL, -}; - -static void free_dynids(struct usb_serial_driver *drv) -{ - struct usb_dynid *dynid, *n; - - spin_lock(&drv->dynids.lock); - list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) { - list_del(&dynid->node); - kfree(dynid); - } - spin_unlock(&drv->dynids.lock); -} - -#else -static struct driver_attribute drv_attrs[] = { - __ATTR_NULL, -}; -static inline void free_dynids(struct usb_driver *drv) -{ -} -#endif - struct bus_type usb_serial_bus_type = { .name = "usb-serial", .match = usb_serial_device_match, .probe = usb_serial_device_probe, .remove = usb_serial_device_remove, - .drv_attrs = drv_attrs, }; int usb_serial_bus_register(struct usb_serial_driver *driver) @@ -156,9 +115,6 @@ int usb_serial_bus_register(struct usb_serial_driver *driver) int retval; driver->driver.bus = &usb_serial_bus_type; - spin_lock_init(&driver->dynids.lock); - INIT_LIST_HEAD(&driver->dynids.list); - retval = driver_register(&driver->driver); return retval; @@ -166,7 +122,6 @@ int usb_serial_bus_register(struct usb_serial_driver *driver) void usb_serial_bus_deregister(struct usb_serial_driver *driver) { - free_dynids(driver); driver_unregister(&driver->driver); } diff --git a/trunk/drivers/usb/serial/cp2101.c b/trunk/drivers/usb/serial/cp2101.c index 06b4fffc189c..7ebaffd6ed86 100644 --- a/trunk/drivers/usb/serial/cp2101.c +++ b/trunk/drivers/usb/serial/cp2101.c @@ -89,7 +89,6 @@ static struct usb_serial_driver cp2101_device = { .owner = THIS_MODULE, .name = "cp2101", }, - .usb_driver = &cp2101_driver, .id_table = id_table, .num_interrupt_in = 0, .num_bulk_in = 0, diff --git a/trunk/drivers/usb/serial/cyberjack.c b/trunk/drivers/usb/serial/cyberjack.c index 4167753ed31f..a63c3286caa0 100644 --- a/trunk/drivers/usb/serial/cyberjack.c +++ b/trunk/drivers/usb/serial/cyberjack.c @@ -88,7 +88,6 @@ static struct usb_serial_driver cyberjack_device = { .name = "cyberjack", }, .description = "Reiner SCT Cyberjack USB card reader", - .usb_driver = &cyberjack_driver, .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -99,7 +98,7 @@ static struct usb_serial_driver cyberjack_device = { .open = cyberjack_open, .close = cyberjack_close, .write = cyberjack_write, - .write_room = cyberjack_write_room, + .write_room = cyberjack_write_room, .read_int_callback = cyberjack_read_int_callback, .read_bulk_callback = cyberjack_read_bulk_callback, .write_bulk_callback = cyberjack_write_bulk_callback, diff --git a/trunk/drivers/usb/serial/cypress_m8.c b/trunk/drivers/usb/serial/cypress_m8.c index 57b8e27285fc..6bc1f404e186 100644 --- a/trunk/drivers/usb/serial/cypress_m8.c +++ b/trunk/drivers/usb/serial/cypress_m8.c @@ -193,7 +193,6 @@ static struct usb_serial_driver cypress_earthmate_device = { .name = "earthmate", }, .description = "DeLorme Earthmate USB", - .usb_driver = &cypress_driver, .id_table = id_table_earthmate, .num_interrupt_in = 1, .num_interrupt_out = 1, @@ -223,7 +222,6 @@ static struct usb_serial_driver cypress_hidcom_device = { .name = "cyphidcom", }, .description = "HID->COM RS232 Adapter", - .usb_driver = &cypress_driver, .id_table = id_table_cyphidcomrs232, .num_interrupt_in = 1, .num_interrupt_out = 1, @@ -253,7 +251,6 @@ static struct usb_serial_driver cypress_ca42v2_device = { .name = "nokiaca42v2", }, .description = "Nokia CA-42 V2 Adapter", - .usb_driver = &cypress_driver, .id_table = id_table_nokiaca42v2, .num_interrupt_in = 1, .num_interrupt_out = 1, diff --git a/trunk/drivers/usb/serial/digi_acceleport.c b/trunk/drivers/usb/serial/digi_acceleport.c index 0b0fb51bad3e..efd9ce3f931f 100644 --- a/trunk/drivers/usb/serial/digi_acceleport.c +++ b/trunk/drivers/usb/serial/digi_acceleport.c @@ -509,7 +509,6 @@ static struct usb_serial_driver digi_acceleport_2_device = { .name = "digi_2", }, .description = "Digi 2 port USB adapter", - .usb_driver = &digi_driver, .id_table = id_table_2, .num_interrupt_in = 0, .num_bulk_in = 4, @@ -539,7 +538,6 @@ static struct usb_serial_driver digi_acceleport_4_device = { .name = "digi_4", }, .description = "Digi 4 port USB adapter", - .usb_driver = &digi_driver, .id_table = id_table_4, .num_interrupt_in = 0, .num_bulk_in = 5, diff --git a/trunk/drivers/usb/serial/empeg.c b/trunk/drivers/usb/serial/empeg.c index 4703c8f85383..92beeb19795f 100644 --- a/trunk/drivers/usb/serial/empeg.c +++ b/trunk/drivers/usb/serial/empeg.c @@ -117,7 +117,6 @@ static struct usb_serial_driver empeg_device = { .name = "empeg", }, .id_table = id_table, - .usb_driver = &empeg_driver, .num_interrupt_in = 0, .num_bulk_in = 1, .num_bulk_out = 1, diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index 4695952b6470..6986e756f7c0 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -464,6 +464,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, + { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) }, @@ -614,7 +615,6 @@ static struct usb_serial_driver ftdi_sio_device = { .name = "ftdi_sio", }, .description = "FTDI USB Serial Device", - .usb_driver = &ftdi_driver , .id_table = id_table_combined, .num_interrupt_in = 0, .num_bulk_in = 1, diff --git a/trunk/drivers/usb/serial/ftdi_sio.h b/trunk/drivers/usb/serial/ftdi_sio.h index 7eff1c03ba80..40dd394de58d 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.h +++ b/trunk/drivers/usb/serial/ftdi_sio.h @@ -364,6 +364,7 @@ * USB-TTY activ, USB-TTY passiv. Some PIDs are used by several devices * and I'm not entirely sure which are used by which. */ +#define FTDI_4N_GALAXY_DE_0_PID 0x8372 #define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 #define FTDI_4N_GALAXY_DE_2_PID 0xF3C1 diff --git a/trunk/drivers/usb/serial/funsoft.c b/trunk/drivers/usb/serial/funsoft.c index 4092f6dc9efd..2bebd63d5ed1 100644 --- a/trunk/drivers/usb/serial/funsoft.c +++ b/trunk/drivers/usb/serial/funsoft.c @@ -58,7 +58,6 @@ static struct usb_serial_driver funsoft_device = { .name = "funsoft", }, .id_table = id_table, - .usb_driver = &funsoft_driver, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE, diff --git a/trunk/drivers/usb/serial/garmin_gps.c b/trunk/drivers/usb/serial/garmin_gps.c index 74660a3aa670..6530d391ebed 100644 --- a/trunk/drivers/usb/serial/garmin_gps.c +++ b/trunk/drivers/usb/serial/garmin_gps.c @@ -1566,7 +1566,6 @@ static struct usb_serial_driver garmin_device = { .name = "garmin_gps", }, .description = "Garmin GPS usb/tty", - .usb_driver = &garmin_driver, .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/trunk/drivers/usb/serial/generic.c b/trunk/drivers/usb/serial/generic.c index 601e0648dec6..36042937e77f 100644 --- a/trunk/drivers/usb/serial/generic.c +++ b/trunk/drivers/usb/serial/generic.c @@ -20,10 +20,6 @@ #include #include -static int generic_probe(struct usb_interface *interface, - const struct usb_device_id *id); - - static int debug; #ifdef CONFIG_USB_SERIAL_GENERIC @@ -38,21 +34,6 @@ MODULE_PARM_DESC(product, "User specified USB idProduct"); static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ -/* we want to look at all devices, as the vendor/product id can change - * depending on the command line argument */ -static struct usb_device_id generic_serial_ids[] = { - {.driver_info = 42}, - {} -}; - -static struct usb_driver generic_driver = { - .name = "usbserial_generic", - .probe = generic_probe, - .disconnect = usb_serial_disconnect, - .id_table = generic_serial_ids, - .no_dynamic_id = 1, -}; - /* All of the device info needed for the Generic Serial Converter */ struct usb_serial_driver usb_serial_generic_device = { .driver = { @@ -60,7 +41,6 @@ struct usb_serial_driver usb_serial_generic_device = { .name = "generic", }, .id_table = generic_device_ids, - .usb_driver = &generic_driver, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE, @@ -68,6 +48,13 @@ struct usb_serial_driver usb_serial_generic_device = { .shutdown = usb_serial_generic_shutdown, }; +/* we want to look at all devices, as the vendor/product id can change + * depending on the command line argument */ +static struct usb_device_id generic_serial_ids[] = { + {.driver_info = 42}, + {} +}; + static int generic_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -78,6 +65,14 @@ static int generic_probe(struct usb_interface *interface, return usb_serial_probe(interface, id); return -ENODEV; } + +static struct usb_driver generic_driver = { + .name = "usbserial_generic", + .probe = generic_probe, + .disconnect = usb_serial_disconnect, + .id_table = generic_serial_ids, + .no_dynamic_id = 1, +}; #endif int usb_serial_generic_register (int _debug) diff --git a/trunk/drivers/usb/serial/hp4x.c b/trunk/drivers/usb/serial/hp4x.c index 6c6ebae741c9..ebcac701b069 100644 --- a/trunk/drivers/usb/serial/hp4x.c +++ b/trunk/drivers/usb/serial/hp4x.c @@ -49,7 +49,6 @@ static struct usb_serial_driver hp49gp_device = { .name = "hp4X", }, .id_table = id_table, - .usb_driver = &hp49gp_driver, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE, diff --git a/trunk/drivers/usb/serial/io_edgeport.c b/trunk/drivers/usb/serial/io_edgeport.c index 6a26a2e683a6..f623d58370a4 100644 --- a/trunk/drivers/usb/serial/io_edgeport.c +++ b/trunk/drivers/usb/serial/io_edgeport.c @@ -146,8 +146,6 @@ struct edgeport_serial { struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ struct edgeport_product_info product_info; /* Product Info */ - struct edge_compatibility_descriptor epic_descriptor; /* Edgeport compatible descriptor */ - int is_epic; /* flag if EPiC device or not */ __u8 interrupt_in_endpoint; /* the interrupt endpoint handle */ unsigned char * interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */ @@ -242,6 +240,14 @@ static void edge_shutdown (struct usb_serial *serial); #include "io_tables.h" /* all of the devices that this driver supports */ +static struct usb_driver io_driver = { + .name = "io_edgeport", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table_combined, + .no_dynamic_id = 1, +}; + /* function prototypes for all of our local functions */ static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength); static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3); @@ -391,7 +397,6 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen) unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2); kfree(pStringDesc); - dbg("%s - USB String %s", __FUNCTION__, string); return strlen(string); } @@ -429,34 +434,6 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de } #endif -static void dump_product_info(struct edgeport_product_info *product_info) -{ - // Dump Product Info structure - dbg("**Product Information:"); - dbg(" ProductId %x", product_info->ProductId ); - dbg(" NumPorts %d", product_info->NumPorts ); - dbg(" ProdInfoVer %d", product_info->ProdInfoVer ); - dbg(" IsServer %d", product_info->IsServer); - dbg(" IsRS232 %d", product_info->IsRS232 ); - dbg(" IsRS422 %d", product_info->IsRS422 ); - dbg(" IsRS485 %d", product_info->IsRS485 ); - dbg(" RomSize %d", product_info->RomSize ); - dbg(" RamSize %d", product_info->RamSize ); - dbg(" CpuRev %x", product_info->CpuRev ); - dbg(" BoardRev %x", product_info->BoardRev); - dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion, - product_info->BootMinorVersion, - le16_to_cpu(product_info->BootBuildNumber)); - dbg(" FirmwareMajorVersion %d.%d.%d", product_info->FirmwareMajorVersion, - product_info->FirmwareMinorVersion, - le16_to_cpu(product_info->FirmwareBuildNumber)); - dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0], - product_info->ManufactureDescDate[1], - product_info->ManufactureDescDate[2]+1900); - dbg(" iDownloadFile 0x%x", product_info->iDownloadFile); - dbg(" EpicVer %d", product_info->EpicVer); -} - static void get_product_info(struct edgeport_serial *edge_serial) { struct edgeport_product_info *product_info = &edge_serial->product_info; @@ -518,60 +495,30 @@ static void get_product_info(struct edgeport_serial *edge_serial) break; } - dump_product_info(product_info); -} - -static int get_epic_descriptor(struct edgeport_serial *ep) -{ - int result; - struct usb_serial *serial = ep->serial; - struct edgeport_product_info *product_info = &ep->product_info; - struct edge_compatibility_descriptor *epic = &ep->epic_descriptor; - struct edge_compatibility_bits *bits; - - ep->is_epic = 0; - result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - USB_REQUEST_ION_GET_EPIC_DESC, - 0xC0, 0x00, 0x00, - &ep->epic_descriptor, - sizeof(struct edge_compatibility_descriptor), - 300); - - dbg("%s result = %d", __FUNCTION__, result); - - if (result > 0) { - ep->is_epic = 1; - memset(product_info, 0, sizeof(struct edgeport_product_info)); - - product_info->NumPorts = epic->NumPorts; - product_info->ProdInfoVer = 0; - product_info->FirmwareMajorVersion = epic->MajorVersion; - product_info->FirmwareMinorVersion = epic->MinorVersion; - product_info->FirmwareBuildNumber = epic->BuildNumber; - product_info->iDownloadFile = epic->iDownloadFile; - product_info->EpicVer = epic->EpicVer; - product_info->Epic = epic->Supports; - product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE; - dump_product_info(product_info); - - bits = &ep->epic_descriptor.Supports; - dbg("**EPIC descriptor:"); - dbg(" VendEnableSuspend: %s", bits->VendEnableSuspend ? "TRUE": "FALSE"); - dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE" ); - dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE" ); - dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE" ); - dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE" ); - dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE" ); - dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE" ); - dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE" ); - dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE" ); - dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE" ); - dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE" ); - dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE" ); - dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE" ); - } + // Dump Product Info structure + dbg("**Product Information:"); + dbg(" ProductId %x", product_info->ProductId ); + dbg(" NumPorts %d", product_info->NumPorts ); + dbg(" ProdInfoVer %d", product_info->ProdInfoVer ); + dbg(" IsServer %d", product_info->IsServer); + dbg(" IsRS232 %d", product_info->IsRS232 ); + dbg(" IsRS422 %d", product_info->IsRS422 ); + dbg(" IsRS485 %d", product_info->IsRS485 ); + dbg(" RomSize %d", product_info->RomSize ); + dbg(" RamSize %d", product_info->RamSize ); + dbg(" CpuRev %x", product_info->CpuRev ); + dbg(" BoardRev %x", product_info->BoardRev); + dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion, + product_info->BootMinorVersion, + le16_to_cpu(product_info->BootBuildNumber)); + dbg(" FirmwareMajorVersion %d.%d.%d", product_info->FirmwareMajorVersion, + product_info->FirmwareMinorVersion, + le16_to_cpu(product_info->FirmwareBuildNumber)); + dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0], + product_info->ManufactureDescDate[1], + product_info->ManufactureDescDate[2]+1900); + dbg(" iDownloadFile 0x%x", product_info->iDownloadFile); - return result; } @@ -1070,30 +1017,22 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) edge_port->closePending = TRUE; - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (edge_serial->epic_descriptor.Supports.IOSPChase))) { - /* flush and chase */ - edge_port->chaseResponsePending = TRUE; - - dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__); - status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); - if (status == 0) { - // block until chase finished - block_until_chase_response(edge_port); - } else { - edge_port->chaseResponsePending = FALSE; - } - } + /* flush and chase */ + edge_port->chaseResponsePending = TRUE; - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (edge_serial->epic_descriptor.Supports.IOSPClose))) { - /* close the port */ - dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__); - send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0); + dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__); + status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); + if (status == 0) { + // block until chase finished + block_until_chase_response(edge_port); + } else { + edge_port->chaseResponsePending = FALSE; } + /* close the port */ + dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__); + send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0); + //port->close = TRUE; edge_port->closePending = FALSE; edge_port->open = FALSE; @@ -1755,38 +1694,29 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned static void edge_break (struct usb_serial_port *port, int break_state) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial); int status; - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (edge_serial->epic_descriptor.Supports.IOSPChase))) { - /* flush and chase */ - edge_port->chaseResponsePending = TRUE; - - dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__); - status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); - if (status == 0) { - // block until chase finished - block_until_chase_response(edge_port); - } else { - edge_port->chaseResponsePending = FALSE; - } + /* flush and chase */ + edge_port->chaseResponsePending = TRUE; + + dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__); + status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); + if (status == 0) { + // block until chase finished + block_until_chase_response(edge_port); + } else { + edge_port->chaseResponsePending = FALSE; } - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) { - if (break_state == -1) { - dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__); - status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0); - } else { - dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__); - status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0); - } - if (status) { - dbg("%s - error sending break set/clear command.", __FUNCTION__); - } + if (break_state == -1) { + dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__); + status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0); + } else { + dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__); + status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0); + } + if (status) { + dbg("%s - error sending break set/clear command.", __FUNCTION__); } return; @@ -2358,7 +2288,6 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer *****************************************************************************/ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate) { - struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); unsigned char *cmdBuffer; unsigned char *currCmd; int cmdLen = 0; @@ -2366,14 +2295,6 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa int status; unsigned char number = edge_port->port->number - edge_port->port->serial->minor; - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate))) { - dbg("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d", - edge_port->port->number, baudRate); - return 0; - } - dbg("%s - port = %d, baud = %d", __FUNCTION__, edge_port->port->number, baudRate); status = calc_baud_rate_divisor (baudRate, &divisor); @@ -2453,7 +2374,6 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor) *****************************************************************************/ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue) { - struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); unsigned char *cmdBuffer; unsigned char *currCmd; unsigned long cmdLen = 0; @@ -2461,22 +2381,6 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue); - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) && - (regNum == MCR))) { - dbg("SendCmdWriteUartReg - Not writting to MCR Register"); - return 0; - } - - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) && - (regNum == LCR))) { - dbg ("SendCmdWriteUartReg - Not writting to LCR Register"); - return 0; - } - // Alloc memory for the string of commands. cmdBuffer = kmalloc (0x10, GFP_ATOMIC); if (cmdBuffer == NULL ) { @@ -2510,7 +2414,6 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r #endif static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) { - struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); struct tty_struct *tty; int baud; unsigned cflag; @@ -2591,12 +2494,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi unsigned char stop_char = STOP_CHAR(tty); unsigned char start_char = START_CHAR(tty); - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (edge_serial->epic_descriptor.Supports.IOSPSetXChar))) { - send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XON_CHAR, start_char); - send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char); - } + send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char); + send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char); /* if we are implementing INBOUND XON/XOFF */ if (I_IXOFF(tty)) { @@ -2616,14 +2515,8 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi } /* Set flow control to the configured value */ - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (edge_serial->epic_descriptor.Supports.IOSPSetRxFlow))) - send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_RX_FLOW, rxFlow); - if ((!edge_serial->is_epic) || - ((edge_serial->is_epic) && - (edge_serial->epic_descriptor.Supports.IOSPSetTxFlow))) - send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_TX_FLOW, txFlow); + send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_RX_FLOW, rxFlow); + send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_TX_FLOW, txFlow); edge_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); @@ -2835,13 +2728,6 @@ static int edge_startup (struct usb_serial *serial) struct edgeport_port *edge_port; struct usb_device *dev; int i, j; - int response; - int interrupt_in_found; - int bulk_in_found; - int bulk_out_found; - static __u32 descriptor[3] = { EDGE_COMPATIBILITY_MASK0, - EDGE_COMPATIBILITY_MASK1, - EDGE_COMPATIBILITY_MASK2 }; dev = serial->dev; @@ -2864,50 +2750,38 @@ static int edge_startup (struct usb_serial *serial) dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); - /* Read the epic descriptor */ - if (get_epic_descriptor(edge_serial) <= 0) { - /* memcpy descriptor to Supports structures */ - memcpy(&edge_serial->epic_descriptor.Supports, descriptor, - sizeof(struct edge_compatibility_bits)); - - /* get the manufacturing descriptor for this device */ - get_manufacturing_desc (edge_serial); + /* get the manufacturing descriptor for this device */ + get_manufacturing_desc (edge_serial); - /* get the boot descriptor */ - get_boot_desc (edge_serial); + /* get the boot descriptor */ + get_boot_desc (edge_serial); - get_product_info(edge_serial); - } + get_product_info(edge_serial); /* set the number of ports from the manufacturing description */ /* serial->num_ports = serial->product_info.NumPorts; */ - if ((!edge_serial->is_epic) && - (edge_serial->product_info.NumPorts != serial->num_ports)) { - dev_warn(&serial->dev->dev, "Device Reported %d serial ports " - "vs. core thinking we have %d ports, email " - "greg@kroah.com this information.", - edge_serial->product_info.NumPorts, - serial->num_ports); + if (edge_serial->product_info.NumPorts != serial->num_ports) { + warn("%s - Device Reported %d serial ports vs core " + "thinking we have %d ports, email greg@kroah.com this info.", + __FUNCTION__, edge_serial->product_info.NumPorts, + serial->num_ports); } dbg("%s - time 1 %ld", __FUNCTION__, jiffies); - /* If not an EPiC device */ - if (!edge_serial->is_epic) { - /* now load the application firmware into this device */ - load_application_firmware (edge_serial); - - dbg("%s - time 2 %ld", __FUNCTION__, jiffies); + /* now load the application firmware into this device */ + load_application_firmware (edge_serial); - /* Check current Edgeport EEPROM and update if necessary */ - update_edgeport_E2PROM (edge_serial); + dbg("%s - time 2 %ld", __FUNCTION__, jiffies); - dbg("%s - time 3 %ld", __FUNCTION__, jiffies); + /* Check current Edgeport EEPROM and update if necessary */ + update_edgeport_E2PROM (edge_serial); + + dbg("%s - time 3 %ld", __FUNCTION__, jiffies); - /* set the configuration to use #1 */ -// dbg("set_configuration 1"); -// usb_set_configuration (dev, 1); - } + /* set the configuration to use #1 */ +// dbg("set_configuration 1"); +// usb_set_configuration (dev, 1); /* we set up the pointers to the endpoints in the edge_open function, * as the structures aren't created yet. */ @@ -2930,101 +2804,8 @@ static int edge_startup (struct usb_serial *serial) edge_port->port = serial->port[i]; usb_set_serial_port_data(serial->port[i], edge_port); } - - response = 0; - - if (edge_serial->is_epic) { - /* EPIC thing, set up our interrupt polling now and our read urb, so - * that the device knows it really is connected. */ - interrupt_in_found = bulk_in_found = bulk_out_found = FALSE; - for (i = 0; i < serial->interface->altsetting[0].desc.bNumEndpoints; ++i) { - struct usb_endpoint_descriptor *endpoint; - int buffer_size; - - endpoint = &serial->interface->altsetting[0].endpoint[i].desc; - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); - if ((!interrupt_in_found) && - (usb_endpoint_is_int_in(endpoint))) { - /* we found a interrupt in endpoint */ - dbg("found interrupt in"); - - /* not set up yet, so do it now */ - edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!edge_serial->interrupt_read_urb) { - err("out of memory"); - return -ENOMEM; - } - edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!edge_serial->interrupt_in_buffer) { - err("out of memory"); - usb_free_urb(edge_serial->interrupt_read_urb); - return -ENOMEM; - } - edge_serial->interrupt_in_endpoint = endpoint->bEndpointAddress; - - /* set up our interrupt urb */ - usb_fill_int_urb(edge_serial->interrupt_read_urb, - dev, - usb_rcvintpipe(dev, endpoint->bEndpointAddress), - edge_serial->interrupt_in_buffer, - buffer_size, - edge_interrupt_callback, - edge_serial, - endpoint->bInterval); - - interrupt_in_found = TRUE; - } - - if ((!bulk_in_found) && - (usb_endpoint_is_bulk_in(endpoint))) { - /* we found a bulk in endpoint */ - dbg("found bulk in"); - - /* not set up yet, so do it now */ - edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!edge_serial->read_urb) { - err("out of memory"); - return -ENOMEM; - } - edge_serial->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!edge_serial->bulk_in_buffer) { - err ("out of memory"); - usb_free_urb(edge_serial->read_urb); - return -ENOMEM; - } - edge_serial->bulk_in_endpoint = endpoint->bEndpointAddress; - - /* set up our bulk in urb */ - usb_fill_bulk_urb(edge_serial->read_urb, dev, - usb_rcvbulkpipe(dev, endpoint->bEndpointAddress), - edge_serial->bulk_in_buffer, - endpoint->wMaxPacketSize, - edge_bulk_in_callback, - edge_serial); - bulk_in_found = TRUE; - } - - if ((!bulk_out_found) && - (usb_endpoint_is_bulk_out(endpoint))) { - /* we found a bulk out endpoint */ - dbg("found bulk out"); - edge_serial->bulk_out_endpoint = endpoint->bEndpointAddress; - bulk_out_found = TRUE; - } - } - - if ((!interrupt_in_found) || (!bulk_in_found) || (!bulk_out_found)) { - err ("Error - the proper endpoints were not found!"); - return -ENODEV; - } - - /* start interrupt read for this edgeport this interrupt will - * continue as long as the edgeport is connected */ - response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL); - if (response) - err("%s - Error %d submitting control urb", __FUNCTION__, response); - } - return response; + + return 0; } @@ -3034,7 +2815,6 @@ static int edge_startup (struct usb_serial *serial) ****************************************************************************/ static void edge_shutdown (struct usb_serial *serial) { - struct edgeport_serial *edge_serial = usb_get_serial_data(serial); int i; dbg("%s", __FUNCTION__); @@ -3044,18 +2824,7 @@ static void edge_shutdown (struct usb_serial *serial) kfree (usb_get_serial_port_data(serial->port[i])); usb_set_serial_port_data(serial->port[i], NULL); } - /* free up our endpoint stuff */ - if (edge_serial->is_epic) { - usb_unlink_urb(edge_serial->interrupt_read_urb); - usb_free_urb(edge_serial->interrupt_read_urb); - kfree(edge_serial->interrupt_in_buffer); - - usb_unlink_urb(edge_serial->read_urb); - usb_free_urb(edge_serial->read_urb); - kfree(edge_serial->bulk_in_buffer); - } - - kfree(edge_serial); + kfree (usb_get_serial_data(serial)); usb_set_serial_data(serial, NULL); } @@ -3077,9 +2846,6 @@ static int __init edgeport_init(void) retval = usb_serial_register(&edgeport_8port_device); if (retval) goto failed_8port_device_register; - retval = usb_serial_register(&epic_device); - if (retval) - goto failed_epic_device_register; retval = usb_register(&io_driver); if (retval) goto failed_usb_register; @@ -3087,8 +2853,6 @@ static int __init edgeport_init(void) return 0; failed_usb_register: - usb_serial_deregister(&epic_device); -failed_epic_device_register: usb_serial_deregister(&edgeport_8port_device); failed_8port_device_register: usb_serial_deregister(&edgeport_4port_device); @@ -3109,7 +2873,6 @@ static void __exit edgeport_exit (void) usb_serial_deregister (&edgeport_2port_device); usb_serial_deregister (&edgeport_4port_device); usb_serial_deregister (&edgeport_8port_device); - usb_serial_deregister (&epic_device); } module_init(edgeport_init); diff --git a/trunk/drivers/usb/serial/io_edgeport.h b/trunk/drivers/usb/serial/io_edgeport.h index 29a913a6daca..123fa8a904e6 100644 --- a/trunk/drivers/usb/serial/io_edgeport.h +++ b/trunk/drivers/usb/serial/io_edgeport.h @@ -111,12 +111,10 @@ struct edgeport_product_info { __le16 FirmwareBuildNumber; /* zzzz (LE format) */ __u8 ManufactureDescDate[3]; /* MM/DD/YY when descriptor template was compiled */ - __u8 HardwareType; + __u8 Unused1[1]; /* Available */ __u8 iDownloadFile; /* What to download to EPiC device */ - __u8 EpicVer; /* What version of EPiC spec this device supports */ - - struct edge_compatibility_bits Epic; + __u8 Unused2[2]; /* Available */ }; /* diff --git a/trunk/drivers/usb/serial/io_tables.h b/trunk/drivers/usb/serial/io_tables.h index 6d3008772540..fad561c04c76 100644 --- a/trunk/drivers/usb/serial/io_tables.h +++ b/trunk/drivers/usb/serial/io_tables.h @@ -47,18 +47,6 @@ static struct usb_device_id edgeport_8port_id_table [] = { { } }; -static struct usb_device_id Epic_port_id_table [] = { - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0202) }, - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0203) }, - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0310) }, - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0311) }, - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0312) }, - { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A758) }, - { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A794) }, - { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A225) }, - { } -}; - /* Devices that this driver supports */ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4) }, @@ -82,34 +70,17 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) }, - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0202) }, - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0203) }, - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0310) }, - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0311) }, - { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0312) }, - { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A758) }, - { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A794) }, - { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A225) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, id_table_combined); -static struct usb_driver io_driver = { - .name = "io_edgeport", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table_combined, - .no_dynamic_id = 1, -}; - static struct usb_serial_driver edgeport_2port_device = { .driver = { .owner = THIS_MODULE, .name = "edgeport_2", }, .description = "Edgeport 2 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_2port_id_table, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -140,7 +111,6 @@ static struct usb_serial_driver edgeport_4port_device = { .name = "edgeport_4", }, .description = "Edgeport 4 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_4port_id_table, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -171,7 +141,6 @@ static struct usb_serial_driver edgeport_8port_device = { .name = "edgeport_8", }, .description = "Edgeport 8 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_8port_id_table, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -196,35 +165,5 @@ static struct usb_serial_driver edgeport_8port_device = { .write_bulk_callback = edge_bulk_out_data_callback, }; -static struct usb_serial_driver epic_device = { - .driver = { - .owner = THIS_MODULE, - .name = "epic", - }, - .description = "EPiC device", - .id_table = Epic_port_id_table, - .num_interrupt_in = 1, - .num_bulk_in = 1, - .num_bulk_out = 1, - .num_ports = 1, - .open = edge_open, - .close = edge_close, - .throttle = edge_throttle, - .unthrottle = edge_unthrottle, - .attach = edge_startup, - .shutdown = edge_shutdown, - .ioctl = edge_ioctl, - .set_termios = edge_set_termios, - .tiocmget = edge_tiocmget, - .tiocmset = edge_tiocmset, - .write = edge_write, - .write_room = edge_write_room, - .chars_in_buffer = edge_chars_in_buffer, - .break_ctl = edge_break, - .read_int_callback = edge_interrupt_callback, - .read_bulk_callback = edge_bulk_in_callback, - .write_bulk_callback = edge_bulk_out_data_callback, -}; - #endif diff --git a/trunk/drivers/usb/serial/io_ti.c b/trunk/drivers/usb/serial/io_ti.c index 544098d2b775..980285c0233a 100644 --- a/trunk/drivers/usb/serial/io_ti.c +++ b/trunk/drivers/usb/serial/io_ti.c @@ -2979,7 +2979,6 @@ static struct usb_serial_driver edgeport_1port_device = { .name = "edgeport_ti_1", }, .description = "Edgeport TI 1 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_1port_id_table, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -3010,7 +3009,6 @@ static struct usb_serial_driver edgeport_2port_device = { .name = "edgeport_ti_2", }, .description = "Edgeport TI 2 port adapter", - .usb_driver = &io_driver, .id_table = edgeport_2port_id_table, .num_interrupt_in = 1, .num_bulk_in = 2, diff --git a/trunk/drivers/usb/serial/io_usbvend.h b/trunk/drivers/usb/serial/io_usbvend.h index e57fa117e486..f1804fd5a3dd 100644 --- a/trunk/drivers/usb/serial/io_usbvend.h +++ b/trunk/drivers/usb/serial/io_usbvend.h @@ -30,7 +30,6 @@ #define USB_VENDOR_ID_ION 0x1608 // Our VID #define USB_VENDOR_ID_TI 0x0451 // TI VID -#define USB_VENDOR_ID_AXIOHM 0x05D9 /* Axiohm VID */ // // Definitions of USB product IDs (PID) @@ -335,10 +334,6 @@ struct edge_compatibility_bits }; -#define EDGE_COMPATIBILITY_MASK0 0x0001 -#define EDGE_COMPATIBILITY_MASK1 0x3FFF -#define EDGE_COMPATIBILITY_MASK2 0x0001 - struct edge_compatibility_descriptor { __u8 Length; // Descriptor Length (per USB spec) diff --git a/trunk/drivers/usb/serial/ipaq.c b/trunk/drivers/usb/serial/ipaq.c index a408184334ea..42f757a5b876 100644 --- a/trunk/drivers/usb/serial/ipaq.c +++ b/trunk/drivers/usb/serial/ipaq.c @@ -563,7 +563,6 @@ static struct usb_serial_driver ipaq_device = { .name = "ipaq", }, .description = "PocketPC PDA", - .usb_driver = &ipaq_driver, .id_table = ipaq_id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 1, diff --git a/trunk/drivers/usb/serial/ipw.c b/trunk/drivers/usb/serial/ipw.c index 1bc586064c77..d3b9a351cef8 100644 --- a/trunk/drivers/usb/serial/ipw.c +++ b/trunk/drivers/usb/serial/ipw.c @@ -442,7 +442,6 @@ static struct usb_serial_driver ipw_device = { .name = "ipw", }, .description = "IPWireless converter", - .usb_driver = &usb_ipw_driver, .id_table = usb_ipw_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 1, diff --git a/trunk/drivers/usb/serial/ir-usb.c b/trunk/drivers/usb/serial/ir-usb.c index 9d847f69291c..8fdf486e3465 100644 --- a/trunk/drivers/usb/serial/ir-usb.c +++ b/trunk/drivers/usb/serial/ir-usb.c @@ -138,7 +138,6 @@ static struct usb_serial_driver ir_device = { .name = "ir-usb", }, .description = "IR Dongle", - .usb_driver = &ir_driver, .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/trunk/drivers/usb/serial/keyspan.c b/trunk/drivers/usb/serial/keyspan.c index e6966f12ed5a..9d2fdfd6865f 100644 --- a/trunk/drivers/usb/serial/keyspan.c +++ b/trunk/drivers/usb/serial/keyspan.c @@ -1275,31 +1275,11 @@ static int keyspan_fake_startup (struct usb_serial *serial) } /* Helper functions used by keyspan_setup_urbs */ -static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial, - int endpoint) -{ - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *ep; - int i; - - iface_desc = serial->interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - ep = &iface_desc->endpoint[i].desc; - if (ep->bEndpointAddress == endpoint) - return ep; - } - dev_warn(&serial->interface->dev, "found no endpoint descriptor for " - "endpoint %x\n", endpoint); - return NULL; -} - static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint, int dir, void *ctx, char *buf, int len, void (*callback)(struct urb *)) { struct urb *urb; - struct usb_endpoint_descriptor const *ep_desc; - char const *ep_type_name; if (endpoint == -1) return NULL; /* endpoint not needed */ @@ -1311,32 +1291,11 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint, return NULL; } - ep_desc = find_ep(serial, endpoint); - if (!ep_desc) { - /* leak the urb, something's wrong and the callers don't care */ - return urb; - } - if (usb_endpoint_xfer_int(ep_desc)) { - ep_type_name = "INT"; - usb_fill_int_urb(urb, serial->dev, - usb_sndintpipe(serial->dev, endpoint) | dir, - buf, len, callback, ctx, - ep_desc->bInterval); - } else if (usb_endpoint_xfer_bulk(ep_desc)) { - ep_type_name = "BULK"; - usb_fill_bulk_urb(urb, serial->dev, - usb_sndbulkpipe(serial->dev, endpoint) | dir, - buf, len, callback, ctx); - } else { - dev_warn(&serial->interface->dev, - "unsupported endpoint type %x\n", - ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); - usb_free_urb(urb); - return NULL; - } + /* Fill URB using supplied data. */ + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, endpoint) | dir, + buf, len, callback, ctx); - dbg("%s - using urb %p for %s endpoint %x", - __func__, urb, ep_type_name, endpoint); return urb; } diff --git a/trunk/drivers/usb/serial/keyspan.h b/trunk/drivers/usb/serial/keyspan.h index c6830cbdc6df..6413d73c139c 100644 --- a/trunk/drivers/usb/serial/keyspan.h +++ b/trunk/drivers/usb/serial/keyspan.h @@ -229,6 +229,7 @@ struct ezusb_hex_record { #define keyspan_usa28_product_id 0x010f #define keyspan_usa28x_product_id 0x0110 #define keyspan_usa28xa_product_id 0x0115 +#define keyspan_usa28xb_product_id 0x0110 #define keyspan_usa49w_product_id 0x010a #define keyspan_usa49wlc_product_id 0x012a @@ -510,6 +511,7 @@ static struct usb_device_id keyspan_ids_combined[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)}, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, { } /* Terminating entry */ @@ -557,6 +559,7 @@ static struct usb_device_id keyspan_2port_ids[] = { { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, + { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, { } /* Terminating entry */ }; @@ -573,7 +576,6 @@ static struct usb_serial_driver keyspan_pre_device = { .name = "keyspan_no_firm", }, .description = "Keyspan - (without firmware)", - .usb_driver = &keyspan_driver, .id_table = keyspan_pre_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -588,7 +590,6 @@ static struct usb_serial_driver keyspan_1port_device = { .name = "keyspan_1", }, .description = "Keyspan 1 port adapter", - .usb_driver = &keyspan_driver, .id_table = keyspan_1port_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -616,7 +617,6 @@ static struct usb_serial_driver keyspan_2port_device = { .name = "keyspan_2", }, .description = "Keyspan 2 port adapter", - .usb_driver = &keyspan_driver, .id_table = keyspan_2port_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -644,7 +644,6 @@ static struct usb_serial_driver keyspan_4port_device = { .name = "keyspan_4", }, .description = "Keyspan 4 port adapter", - .usb_driver = &keyspan_driver, .id_table = keyspan_4port_ids, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 5, diff --git a/trunk/drivers/usb/serial/keyspan_pda.c b/trunk/drivers/usb/serial/keyspan_pda.c index da514cb785b3..126b9703bbaf 100644 --- a/trunk/drivers/usb/serial/keyspan_pda.c +++ b/trunk/drivers/usb/serial/keyspan_pda.c @@ -793,7 +793,6 @@ static struct usb_serial_driver keyspan_pda_fake_device = { .name = "keyspan_pda_pre", }, .description = "Keyspan PDA - (prerenumeration)", - .usb_driver = &keyspan_pda_driver, .id_table = id_table_fake, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -810,7 +809,6 @@ static struct usb_serial_driver xircom_pgs_fake_device = { .name = "xircom_no_firm", }, .description = "Xircom / Entregra PGS - (prerenumeration)", - .usb_driver = &keyspan_pda_driver, .id_table = id_table_fake_xircom, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -826,7 +824,6 @@ static struct usb_serial_driver keyspan_pda_device = { .name = "keyspan_pda", }, .description = "Keyspan PDA", - .usb_driver = &keyspan_pda_driver, .id_table = id_table_std, .num_interrupt_in = 1, .num_bulk_in = 0, diff --git a/trunk/drivers/usb/serial/kl5kusb105.c b/trunk/drivers/usb/serial/kl5kusb105.c index b2097c45a235..5c4b06a99ac0 100644 --- a/trunk/drivers/usb/serial/kl5kusb105.c +++ b/trunk/drivers/usb/serial/kl5kusb105.c @@ -124,7 +124,6 @@ static struct usb_serial_driver kl5kusb105d_device = { .name = "kl5kusb105d", }, .description = "KL5KUSB105D / PalmConnect", - .usb_driver = &kl5kusb105d_driver, .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/trunk/drivers/usb/serial/kobil_sct.c b/trunk/drivers/usb/serial/kobil_sct.c index 0683b51f0932..62bea0c923bd 100644 --- a/trunk/drivers/usb/serial/kobil_sct.c +++ b/trunk/drivers/usb/serial/kobil_sct.c @@ -110,7 +110,6 @@ static struct usb_serial_driver kobil_device = { .name = "kobil", }, .description = "KOBIL USB smart card terminal", - .usb_driver = &kobil_driver, .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 0, diff --git a/trunk/drivers/usb/serial/mct_u232.c b/trunk/drivers/usb/serial/mct_u232.c index 4cd839b1407f..38b1d17e06ef 100644 --- a/trunk/drivers/usb/serial/mct_u232.c +++ b/trunk/drivers/usb/serial/mct_u232.c @@ -137,7 +137,6 @@ static struct usb_serial_driver mct_u232_device = { .name = "mct_u232", }, .description = "MCT U232", - .usb_driver = &mct_u232_driver, .id_table = id_table_combined, .num_interrupt_in = 2, .num_bulk_in = 0, diff --git a/trunk/drivers/usb/serial/mos7720.c b/trunk/drivers/usb/serial/mos7720.c index 6109c6704a73..e55f4ed81d7b 100644 --- a/trunk/drivers/usb/serial/mos7720.c +++ b/trunk/drivers/usb/serial/mos7720.c @@ -1605,21 +1605,12 @@ static void mos7720_shutdown(struct usb_serial *serial) usb_set_serial_data(serial, NULL); } -static struct usb_driver usb_driver = { - .name = "moschip7720", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = moschip_port_id_table, - .no_dynamic_id = 1, -}; - static struct usb_serial_driver moschip7720_2port_driver = { .driver = { .owner = THIS_MODULE, .name = "moschip7720", }, .description = "Moschip 2 port adapter", - .usb_driver = &usb_driver, .id_table = moschip_port_id_table, .num_interrupt_in = 1, .num_bulk_in = 2, @@ -1640,6 +1631,13 @@ static struct usb_serial_driver moschip7720_2port_driver = { .read_bulk_callback = mos7720_bulk_in_callback, }; +static struct usb_driver usb_driver = { + .name = "moschip7720", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = moschip_port_id_table, +}; + static int __init moschip7720_init(void) { int retval; diff --git a/trunk/drivers/usb/serial/mos7840.c b/trunk/drivers/usb/serial/mos7840.c index b2264a87617b..83f661403ba1 100644 --- a/trunk/drivers/usb/serial/mos7840.c +++ b/trunk/drivers/usb/serial/mos7840.c @@ -2834,21 +2834,12 @@ static void mos7840_shutdown(struct usb_serial *serial) } -static struct usb_driver io_driver = { - .name = "mos7840", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = moschip_id_table_combined, - .no_dynamic_id = 1, -}; - static struct usb_serial_driver moschip7840_4port_device = { .driver = { .owner = THIS_MODULE, .name = "mos7840", }, .description = DRIVER_DESC, - .usb_driver = &io_driver, .id_table = moschip_port_id_table, .num_interrupt_in = 1, //NUM_DONT_CARE,//1, #ifdef check @@ -2878,6 +2869,13 @@ static struct usb_serial_driver moschip7840_4port_device = { .read_int_callback = mos7840_interrupt_callback, }; +static struct usb_driver io_driver = { + .name = "mos7840", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = moschip_id_table_combined, +}; + /**************************************************************************** * moschip7840_init * This is called by the module subsystem, or on startup to initialize us diff --git a/trunk/drivers/usb/serial/navman.c b/trunk/drivers/usb/serial/navman.c index 90701111d746..054abee81652 100644 --- a/trunk/drivers/usb/serial/navman.c +++ b/trunk/drivers/usb/serial/navman.c @@ -119,7 +119,6 @@ static struct usb_serial_driver navman_device = { .name = "navman", }, .id_table = id_table, - .usb_driver = &navman_driver, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE, diff --git a/trunk/drivers/usb/serial/omninet.c b/trunk/drivers/usb/serial/omninet.c index 0216ac12a27d..bc91d3b726fc 100644 --- a/trunk/drivers/usb/serial/omninet.c +++ b/trunk/drivers/usb/serial/omninet.c @@ -93,7 +93,6 @@ static struct usb_serial_driver zyxel_omninet_device = { .name = "omninet", }, .description = "ZyXEL - omni.net lcd plus usb", - .usb_driver = &omninet_driver, .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index ced9f32b29d9..0fed43a96871 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -135,7 +135,6 @@ static struct usb_serial_driver option_1port_device = { .name = "option1", }, .description = "GSM modem (1-port)", - .usb_driver = &option_driver, .id_table = option_ids1, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, diff --git a/trunk/drivers/usb/serial/pl2303.c b/trunk/drivers/usb/serial/pl2303.c index 6c083d4e2c9b..5dc2ac9afa90 100644 --- a/trunk/drivers/usb/serial/pl2303.c +++ b/trunk/drivers/usb/serial/pl2303.c @@ -1118,7 +1118,6 @@ static struct usb_serial_driver pl2303_device = { .name = "pl2303", }, .id_table = id_table, - .usb_driver = &pl2303_driver, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 1, .num_bulk_out = 1, diff --git a/trunk/drivers/usb/serial/safe_serial.c b/trunk/drivers/usb/serial/safe_serial.c index 5a03a3fc9386..30b7ebc8d45d 100644 --- a/trunk/drivers/usb/serial/safe_serial.c +++ b/trunk/drivers/usb/serial/safe_serial.c @@ -402,7 +402,6 @@ static struct usb_serial_driver safe_device = { .name = "safe_serial", }, .id_table = id_table, - .usb_driver = &safe_driver, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE, diff --git a/trunk/drivers/usb/serial/sierra.c b/trunk/drivers/usb/serial/sierra.c index ecedd833818d..6d8e91e00ecf 100644 --- a/trunk/drivers/usb/serial/sierra.c +++ b/trunk/drivers/usb/serial/sierra.c @@ -13,9 +13,10 @@ Portions based on the option driver by Matthias Urlichs Whom based his on the Keyspan driver by Hugh Blemings + History: */ -#define DRIVER_VERSION "v.1.0.6" +#define DRIVER_VERSION "v.1.0.5" #define DRIVER_AUTHOR "Kevin Lloyd " #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" @@ -30,15 +31,14 @@ static struct usb_device_id id_table [] = { - { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ - { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ - { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ + { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ - { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ + { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 for Europe */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ @@ -55,15 +55,14 @@ static struct usb_device_id id_table_1port [] = { }; static struct usb_device_id id_table_3port [] = { - { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ - { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ - { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ + { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ - { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ + { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 for Europe */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ { } @@ -82,7 +81,7 @@ static int debug; /* per port private data */ #define N_IN_URB 4 -#define N_OUT_URB 4 +#define N_OUT_URB 1 #define IN_BUFLEN 4096 #define OUT_BUFLEN 128 @@ -397,8 +396,6 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) struct usb_serial *serial = port->serial; int i, err; struct urb *urb; - int result; - __u16 set_mode_dzero = 0x0000; portdata = usb_get_serial_port_data(port); @@ -445,12 +442,6 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) port->tty->low_latency = 1; - /* set mode to D0 */ - result = usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 0x00, 0x40, set_mode_dzero, 0, NULL, - 0, USB_CTRL_SET_TIMEOUT); - sierra_send_setup(port); return (0); @@ -623,7 +614,6 @@ static struct usb_serial_driver sierra_1port_device = { }, .description = "Sierra USB modem (1 port)", .id_table = id_table_1port, - .usb_driver = &sierra_driver, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 1, .num_bulk_out = 1, @@ -652,7 +642,6 @@ static struct usb_serial_driver sierra_3port_device = { }, .description = "Sierra USB modem (3 port)", .id_table = id_table_3port, - .usb_driver = &sierra_driver, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 3, .num_bulk_out = 3, diff --git a/trunk/drivers/usb/serial/ti_usb_3410_5052.c b/trunk/drivers/usb/serial/ti_usb_3410_5052.c index 4203e2b1a761..83189005c6fb 100644 --- a/trunk/drivers/usb/serial/ti_usb_3410_5052.c +++ b/trunk/drivers/usb/serial/ti_usb_3410_5052.c @@ -262,7 +262,6 @@ static struct usb_serial_driver ti_1port_device = { .name = "ti_usb_3410_5052_1", }, .description = "TI USB 3410 1 port adapter", - .usb_driver = &ti_usb_driver, .id_table = ti_id_table_3410, .num_interrupt_in = 1, .num_bulk_in = 1, @@ -293,7 +292,6 @@ static struct usb_serial_driver ti_2port_device = { .name = "ti_usb_3410_5052_2", }, .description = "TI USB 5052 2 port adapter", - .usb_driver = &ti_usb_driver, .id_table = ti_id_table_5052, .num_interrupt_in = 1, .num_bulk_in = 2, diff --git a/trunk/drivers/usb/serial/usb-serial.c b/trunk/drivers/usb/serial/usb-serial.c index 6bf22a28adb8..716f6806cc89 100644 --- a/trunk/drivers/usb/serial/usb-serial.c +++ b/trunk/drivers/usb/serial/usb-serial.c @@ -59,19 +59,14 @@ static struct usb_driver usb_serial_driver = { static int debug; static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ -static spinlock_t table_lock; static LIST_HEAD(usb_serial_driver_list); struct usb_serial *usb_serial_get_by_index(unsigned index) { - struct usb_serial *serial; - - spin_lock(&table_lock); - serial = serial_table[index]; + struct usb_serial *serial = serial_table[index]; if (serial) kref_get(&serial->kref); - spin_unlock(&table_lock); return serial; } @@ -83,7 +78,6 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po dbg("%s %d", __FUNCTION__, num_ports); *minor = 0; - spin_lock(&table_lock); for (i = 0; i < SERIAL_TTY_MINORS; ++i) { if (serial_table[i]) continue; @@ -102,10 +96,8 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po dbg("%s - minor base = %d", __FUNCTION__, *minor); for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) serial_table[i] = serial; - spin_unlock(&table_lock); return serial; } - spin_unlock(&table_lock); return NULL; } @@ -118,11 +110,9 @@ static void return_serial(struct usb_serial *serial) if (serial == NULL) return; - spin_lock(&table_lock); for (i = 0; i < serial->num_ports; ++i) { serial_table[serial->minor + i] = NULL; } - spin_unlock(&table_lock); } static void destroy_serial(struct kref *kref) @@ -281,7 +271,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp) static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) { struct usb_serial_port *port = tty->driver_data; - int retval = -ENODEV; + int retval = -EINVAL; if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) goto exit; @@ -289,7 +279,6 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); if (!port->open_count) { - retval = -EINVAL; dbg("%s - port not opened", __FUNCTION__); goto exit; } @@ -570,20 +559,15 @@ static void port_release(struct device *dev) port_free(port); } -static void kill_traffic(struct usb_serial_port *port) -{ - usb_kill_urb(port->read_urb); - usb_kill_urb(port->write_urb); - usb_kill_urb(port->interrupt_in_urb); - usb_kill_urb(port->interrupt_out_urb); -} - static void port_free(struct usb_serial_port *port) { - kill_traffic(port); + usb_kill_urb(port->read_urb); usb_free_urb(port->read_urb); + usb_kill_urb(port->write_urb); usb_free_urb(port->write_urb); + usb_kill_urb(port->interrupt_in_urb); usb_free_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_out_urb); usb_free_urb(port->interrupt_out_urb); kfree(port->bulk_in_buffer); kfree(port->bulk_out_buffer); @@ -612,39 +596,6 @@ static struct usb_serial * create_serial (struct usb_device *dev, return serial; } -static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf, - struct usb_serial_driver *drv) -{ - struct usb_dynid *dynid; - - spin_lock(&drv->dynids.lock); - list_for_each_entry(dynid, &drv->dynids.list, node) { - if (usb_match_one_id(intf, &dynid->id)) { - spin_unlock(&drv->dynids.lock); - return &dynid->id; - } - } - spin_unlock(&drv->dynids.lock); - return NULL; -} - -static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv, - struct usb_interface *intf) -{ - const struct usb_device_id *id; - - id = usb_match_id(intf, drv->id_table); - if (id) { - dbg("static descriptor matches"); - goto exit; - } - id = match_dynamic_id(intf, drv); - if (id) - dbg("dynamic descriptor matches"); -exit: - return id; -} - static struct usb_serial_driver *search_serial_device(struct usb_interface *iface) { struct list_head *p; @@ -654,9 +605,11 @@ static struct usb_serial_driver *search_serial_device(struct usb_interface *ifac /* Check if the usb id matches a known device */ list_for_each(p, &usb_serial_driver_list) { t = list_entry(p, struct usb_serial_driver, driver_list); - id = get_iface_id(t, iface); - if (id) + id = usb_match_id(iface, t->id_table); + if (id != NULL) { + dbg("descriptor matches"); return t; + } } return NULL; @@ -686,17 +639,14 @@ int usb_serial_probe(struct usb_interface *interface, int num_ports = 0; int max_endpoints; - lock_kernel(); /* guard against unloading a serial driver module */ type = search_serial_device(interface); if (!type) { - unlock_kernel(); dbg("none matched"); return -ENODEV; } serial = create_serial (dev, interface, type); if (!serial) { - unlock_kernel(); dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); return -ENOMEM; } @@ -706,18 +656,16 @@ int usb_serial_probe(struct usb_interface *interface, const struct usb_device_id *id; if (!try_module_get(type->driver.owner)) { - unlock_kernel(); dev_err(&interface->dev, "module get failed, exiting\n"); kfree (serial); return -EIO; } - id = get_iface_id(type, interface); + id = usb_match_id(interface, type->id_table); retval = type->probe(serial, id); module_put(type->driver.owner); if (retval) { - unlock_kernel(); dbg ("sub driver rejected device"); kfree (serial); return retval; @@ -787,7 +735,6 @@ int usb_serial_probe(struct usb_interface *interface, * properly during a later invocation of usb_serial_probe */ if (num_bulk_in == 0 || num_bulk_out == 0) { - unlock_kernel(); dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); kfree (serial); return -ENODEV; @@ -803,7 +750,6 @@ int usb_serial_probe(struct usb_interface *interface, if (type == &usb_serial_generic_device) { num_ports = num_bulk_out; if (num_ports == 0) { - unlock_kernel(); dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); kfree (serial); return -EIO; @@ -814,7 +760,6 @@ int usb_serial_probe(struct usb_interface *interface, /* if this device type has a calc_num_ports function, call it */ if (type->calc_num_ports) { if (!try_module_get(type->driver.owner)) { - unlock_kernel(); dev_err(&interface->dev, "module get failed, exiting\n"); kfree (serial); return -EIO; @@ -826,6 +771,12 @@ int usb_serial_probe(struct usb_interface *interface, num_ports = type->num_ports; } + if (get_free_serial (serial, num_ports, &minor) == NULL) { + dev_err(&interface->dev, "No more free serial devices\n"); + kfree (serial); + return -ENOMEM; + } + serial->minor = minor; serial->num_ports = num_ports; serial->num_bulk_in = num_bulk_in; @@ -840,8 +791,6 @@ int usb_serial_probe(struct usb_interface *interface, max_endpoints = max(max_endpoints, num_interrupt_out); max_endpoints = max(max_endpoints, (int)serial->num_ports); serial->num_port_pointers = max_endpoints; - unlock_kernel(); - dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints); for (i = 0; i < max_endpoints; ++i) { port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); @@ -976,11 +925,6 @@ int usb_serial_probe(struct usb_interface *interface, } } - if (get_free_serial (serial, num_ports, &minor) == NULL) { - dev_err(&interface->dev, "No more free serial devices\n"); - goto probe_error; - } - /* register all of the individual ports with the driver core */ for (i = 0; i < num_ports; ++i) { port = serial->port[i]; @@ -1058,11 +1002,8 @@ void usb_serial_disconnect(struct usb_interface *interface) if (serial) { for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; - if (port) { - if (port->tty) - tty_hangup(port->tty); - kill_traffic(port); - } + if (port && port->tty) + tty_hangup(port->tty); } /* let the last holder of this object * cause it to be cleaned up */ @@ -1099,7 +1040,6 @@ static int __init usb_serial_init(void) return -ENOMEM; /* Initialize our global data */ - spin_lock_init(&table_lock); for (i = 0; i < SERIAL_TTY_MINORS; ++i) { serial_table[i] = NULL; } @@ -1198,7 +1138,7 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, shutdown); } -int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */ +int usb_serial_register(struct usb_serial_driver *driver) { int retval; @@ -1222,7 +1162,7 @@ int usb_serial_register(struct usb_serial_driver *driver) /* must be called with } -void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */ +void usb_serial_deregister(struct usb_serial_driver *device) { info("USB Serial deregistering driver %s", device->description); list_del(&device->driver_list); diff --git a/trunk/drivers/usb/serial/visor.c b/trunk/drivers/usb/serial/visor.c index 2f59ff226e2c..b09f06096056 100644 --- a/trunk/drivers/usb/serial/visor.c +++ b/trunk/drivers/usb/serial/visor.c @@ -90,6 +90,8 @@ static struct usb_device_id id_table [] = { .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID), @@ -149,6 +151,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) }, + { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID) }, { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) }, @@ -186,7 +189,6 @@ static struct usb_serial_driver handspring_device = { .name = "visor", }, .description = "Handspring Visor / Palm OS", - .usb_driver = &visor_driver, .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 2, @@ -217,7 +219,6 @@ static struct usb_serial_driver clie_5_device = { .name = "clie_5", }, .description = "Sony Clie 5.0", - .usb_driver = &visor_driver, .id_table = clie_id_5_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 2, @@ -248,7 +249,6 @@ static struct usb_serial_driver clie_3_5_device = { .name = "clie_3.5", }, .description = "Sony Clie 3.5", - .usb_driver = &visor_driver, .id_table = clie_id_3_5_table, .num_interrupt_in = 0, .num_bulk_in = 1, diff --git a/trunk/drivers/usb/serial/visor.h b/trunk/drivers/usb/serial/visor.h index 4ce6f62a6f39..765118d83fb6 100644 --- a/trunk/drivers/usb/serial/visor.h +++ b/trunk/drivers/usb/serial/visor.h @@ -32,6 +32,7 @@ #define PALM_TUNGSTEN_T_ID 0x0060 #define PALM_TREO_650 0x0061 #define PALM_TUNGSTEN_Z_ID 0x0031 +#define PALM_ZIRE31_ID 0x0061 #define PALM_ZIRE_ID 0x0070 #define PALM_M100_ID 0x0080 diff --git a/trunk/drivers/usb/serial/whiteheat.c b/trunk/drivers/usb/serial/whiteheat.c index bf16e9e1d84e..5483d8564c1b 100644 --- a/trunk/drivers/usb/serial/whiteheat.c +++ b/trunk/drivers/usb/serial/whiteheat.c @@ -161,7 +161,6 @@ static struct usb_serial_driver whiteheat_fake_device = { .name = "whiteheatnofirm", }, .description = "Connect Tech - WhiteHEAT - (prerenumeration)", - .usb_driver = &whiteheat_driver, .id_table = id_table_prerenumeration, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, @@ -177,7 +176,6 @@ static struct usb_serial_driver whiteheat_device = { .name = "whiteheat", }, .description = "Connect Tech - WhiteHEAT", - .usb_driver = &whiteheat_driver, .id_table = id_table_std, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, diff --git a/trunk/drivers/usb/storage/onetouch.c b/trunk/drivers/usb/storage/onetouch.c index 6d3dad3d1dae..e565d3d2ab29 100644 --- a/trunk/drivers/usb/storage/onetouch.c +++ b/trunk/drivers/usb/storage/onetouch.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "usb.h" #include "onetouch.h" diff --git a/trunk/drivers/usb/storage/scsiglue.c b/trunk/drivers/usb/storage/scsiglue.c index 70234f5dbeeb..e1072d52d641 100644 --- a/trunk/drivers/usb/storage/scsiglue.c +++ b/trunk/drivers/usb/storage/scsiglue.c @@ -110,6 +110,23 @@ static int slave_configure(struct scsi_device *sdev) * the end, scatter-gather buffers follow page boundaries. */ blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); + /* Set the SCSI level to at least 2. We'll leave it at 3 if that's + * what is originally reported. We need this to avoid confusing + * the SCSI layer with devices that report 0 or 1, but need 10-byte + * commands (ala ATAPI devices behind certain bridges, or devices + * which simply have broken INQUIRY data). + * + * NOTE: This means /dev/sg programs (ala cdrecord) will get the + * actual information. This seems to be the preference for + * programs like that. + * + * NOTE: This also means that /proc/scsi/scsi and sysfs may report + * the actual value or the modified one, depending on where the + * data comes from. + */ + if (sdev->scsi_level < SCSI_2) + sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2; + /* Many devices have trouble transfering more than 32KB at a time, * while others have trouble with more than 64K. At this time we * are limiting both to 32K (64 sectores). @@ -159,9 +176,7 @@ static int slave_configure(struct scsi_device *sdev) * a Get-Max-LUN request, we won't lose much by setting the * revision level down to 2. The only devices that would be * affected are those with sparse LUNs. */ - if (sdev->scsi_level > SCSI_2) - sdev->sdev_target->scsi_level = - sdev->scsi_level = SCSI_2; + sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2; /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable * Hardware Error) when any low-level error occurs, @@ -179,16 +194,6 @@ static int slave_configure(struct scsi_device *sdev) sdev->use_10_for_ms = 1; } - /* The CB and CBI transports have no way to pass LUN values - * other than the bits in the second byte of a CDB. But those - * bits don't get set to the LUN value if the device reports - * scsi_level == 0 (UNKNOWN). Hence such devices must necessarily - * be single-LUN. - */ - if ((us->protocol == US_PR_CB || us->protocol == US_PR_CBI) && - sdev->scsi_level == SCSI_UNKNOWN) - us->max_lun = 0; - /* Some devices choke when they receive a PREVENT-ALLOW MEDIUM * REMOVAL command, so suppress those commands. */ if (us->flags & US_FL_NOT_LOCKABLE) diff --git a/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index f49a62fc32d2..b49f2a78189e 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/drivers/usb/storage/unusual_devs.h @@ -573,7 +573,7 @@ UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, #endif /* Submitted by Olaf Hering, SuSE Bugzilla #49049 */ -UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x2000, +UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x0501, "Sony", "USB Floppy Drive", US_SC_DEVICE, US_PR_DEVICE, NULL, @@ -1325,6 +1325,13 @@ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Jan Mate */ +UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, + "Sony Ericsson", + "P990i", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. diff --git a/trunk/drivers/usb/storage/usb.c b/trunk/drivers/usb/storage/usb.c index 7e7ec29782f1..70644506651f 100644 --- a/trunk/drivers/usb/storage/usb.c +++ b/trunk/drivers/usb/storage/usb.c @@ -731,27 +731,26 @@ static int get_pipes(struct us_data *us) struct usb_endpoint_descriptor *ep_int = NULL; /* - * Find the first endpoint of each type we need. + * Find the endpoints we need. * We are expecting a minimum of 2 endpoints - in and out (bulk). - * An optional interrupt-in is OK (necessary for CBI protocol). + * An optional interrupt is OK (necessary for CBI protocol). * We will ignore any others. */ for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { ep = &altsetting->endpoint[i].desc; + /* Is it a BULK endpoint? */ if (usb_endpoint_xfer_bulk(ep)) { - if (usb_endpoint_dir_in(ep)) { - if (!ep_in) - ep_in = ep; - } else { - if (!ep_out) - ep_out = ep; - } + /* BULK in or out? */ + if (usb_endpoint_dir_in(ep)) + ep_in = ep; + else + ep_out = ep; } - else if (usb_endpoint_is_int_in(ep)) { - if (!ep_int) - ep_int = ep; + /* Is it an interrupt endpoint? */ + else if (usb_endpoint_xfer_int(ep)) { + ep_int = ep; } } diff --git a/trunk/fs/sysfs/bin.c b/trunk/fs/sysfs/bin.c index d3b9f5f07db1..e8f540d38d48 100644 --- a/trunk/fs/sysfs/bin.c +++ b/trunk/fs/sysfs/bin.c @@ -16,7 +16,6 @@ #include #include -#include #include "sysfs.h" @@ -147,7 +146,7 @@ static int open(struct inode * inode, struct file * file) Error: module_put(attr->attr.owner); Done: - if (error) + if (error && kobj) kobject_put(kobj); return error; } @@ -158,7 +157,8 @@ static int release(struct inode * inode, struct file * file) struct bin_attribute * attr = to_bin_attr(file->f_path.dentry); u8 * buffer = file->private_data; - kobject_put(kobj); + if (kobj) + kobject_put(kobj); module_put(attr->attr.owner); kfree(buffer); return 0; diff --git a/trunk/fs/sysfs/dir.c b/trunk/fs/sysfs/dir.c index 9dcdf556c99c..511edef8b321 100644 --- a/trunk/fs/sysfs/dir.c +++ b/trunk/fs/sysfs/dir.c @@ -9,7 +9,6 @@ #include #include #include -#include #include "sysfs.h" DECLARE_RWSEM(sysfs_rename_sem); @@ -33,7 +32,8 @@ static struct dentry_operations sysfs_dentry_ops = { /* * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent */ -static struct sysfs_dirent * __sysfs_new_dirent(void * element) +static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd, + void * element) { struct sysfs_dirent * sd; @@ -45,28 +45,12 @@ static struct sysfs_dirent * __sysfs_new_dirent(void * element) atomic_set(&sd->s_count, 1); atomic_set(&sd->s_event, 1); INIT_LIST_HEAD(&sd->s_children); - INIT_LIST_HEAD(&sd->s_sibling); + list_add(&sd->s_sibling, &parent_sd->s_children); sd->s_element = element; return sd; } -static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd, - struct sysfs_dirent *sd) -{ - if (sd) - list_add(&sd->s_sibling, &parent_sd->s_children); -} - -static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd, - void * element) -{ - struct sysfs_dirent *sd; - sd = __sysfs_new_dirent(element); - __sysfs_list_dirent(parent_sd, sd); - return sd; -} - /* * * Return -EEXIST if there is already a sysfs element with the same name for @@ -93,14 +77,14 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, } -static struct sysfs_dirent * -__sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type) +int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, + void * element, umode_t mode, int type) { struct sysfs_dirent * sd; - sd = __sysfs_new_dirent(element); + sd = sysfs_new_dirent(parent_sd, element); if (!sd) - goto out; + return -ENOMEM; sd->s_mode = mode; sd->s_type = type; @@ -110,19 +94,7 @@ __sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type) dentry->d_op = &sysfs_dentry_ops; } -out: - return sd; -} - -int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, - void * element, umode_t mode, int type) -{ - struct sysfs_dirent *sd; - - sd = __sysfs_make_dirent(dentry, element, mode, type); - __sysfs_list_dirent(parent_sd, sd); - - return sd ? 0 : -ENOMEM; + return 0; } static int init_dir(struct inode * inode) @@ -193,11 +165,11 @@ int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d) /** * sysfs_create_dir - create a directory for an object. + * @parent: parent parent object. * @kobj: object we're creating directory for. - * @shadow_parent: parent parent object. */ -int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent) +int sysfs_create_dir(struct kobject * kobj) { struct dentry * dentry = NULL; struct dentry * parent; @@ -205,9 +177,7 @@ int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent) BUG_ON(!kobj); - if (shadow_parent) - parent = shadow_parent; - else if (kobj->parent) + if (kobj->parent) parent = kobj->parent->dentry; else if (sysfs_mount && sysfs_mount->mnt_sb) parent = sysfs_mount->mnt_sb->s_root; @@ -328,12 +298,21 @@ void sysfs_remove_subdir(struct dentry * d) } -static void __sysfs_remove_dir(struct dentry *dentry) +/** + * sysfs_remove_dir - remove an object's directory. + * @kobj: object. + * + * The only thing special about this is that we remove any files in + * the directory before we remove the directory, and we've inlined + * what used to be sysfs_rmdir() below, instead of calling separately. + */ + +void sysfs_remove_dir(struct kobject * kobj) { + struct dentry * dentry = dget(kobj->dentry); struct sysfs_dirent * parent_sd; struct sysfs_dirent * sd, * tmp; - dget(dentry); if (!dentry) return; @@ -354,60 +333,32 @@ static void __sysfs_remove_dir(struct dentry *dentry) * Drop reference from dget() on entrance. */ dput(dentry); -} - -/** - * sysfs_remove_dir - remove an object's directory. - * @kobj: object. - * - * The only thing special about this is that we remove any files in - * the directory before we remove the directory, and we've inlined - * what used to be sysfs_rmdir() below, instead of calling separately. - */ - -void sysfs_remove_dir(struct kobject * kobj) -{ - __sysfs_remove_dir(kobj->dentry); kobj->dentry = NULL; } -int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, - const char *new_name) +int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { int error = 0; - struct dentry * new_dentry; + struct dentry * new_dentry, * parent; - if (!new_parent) - return -EFAULT; + if (!strcmp(kobject_name(kobj), new_name)) + return -EINVAL; + + if (!kobj->parent) + return -EINVAL; down_write(&sysfs_rename_sem); - mutex_lock(&new_parent->d_inode->i_mutex); + parent = kobj->parent->dentry; + + mutex_lock(&parent->d_inode->i_mutex); - new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); + new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); if (!IS_ERR(new_dentry)) { - /* By allowing two different directories with the - * same d_parent we allow this routine to move - * between different shadows of the same directory - */ - if (kobj->dentry->d_parent->d_inode != new_parent->d_inode) - return -EINVAL; - else if (new_dentry->d_parent->d_inode != new_parent->d_inode) - error = -EINVAL; - else if (new_dentry == kobj->dentry) - error = -EINVAL; - else if (!new_dentry->d_inode) { + if (!new_dentry->d_inode) { error = kobject_set_name(kobj, "%s", new_name); if (!error) { - struct sysfs_dirent *sd, *parent_sd; - d_add(new_dentry, NULL); d_move(kobj->dentry, new_dentry); - - sd = kobj->dentry->d_fsdata; - parent_sd = new_parent->d_fsdata; - - list_del_init(&sd->s_sibling); - list_add(&sd->s_sibling, &parent_sd->s_children); } else d_drop(new_dentry); @@ -415,7 +366,7 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, error = -EEXIST; dput(new_dentry); } - mutex_unlock(&new_parent->d_inode->i_mutex); + mutex_unlock(&parent->d_inode->i_mutex); up_write(&sysfs_rename_sem); return error; @@ -427,10 +378,12 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) struct sysfs_dirent *new_parent_sd, *sd; int error; + if (!new_parent) + return -EINVAL; + old_parent_dentry = kobj->parent ? kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; - new_parent_dentry = new_parent ? - new_parent->dentry : sysfs_mount->mnt_sb->s_root; + new_parent_dentry = new_parent->dentry; again: mutex_lock(&old_parent_dentry->d_inode->i_mutex); @@ -594,95 +547,6 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) return offset; } - -/** - * sysfs_make_shadowed_dir - Setup so a directory can be shadowed - * @kobj: object we're creating shadow of. - */ - -int sysfs_make_shadowed_dir(struct kobject *kobj, - void * (*follow_link)(struct dentry *, struct nameidata *)) -{ - struct inode *inode; - struct inode_operations *i_op; - - inode = kobj->dentry->d_inode; - if (inode->i_op != &sysfs_dir_inode_operations) - return -EINVAL; - - i_op = kmalloc(sizeof(*i_op), GFP_KERNEL); - if (!i_op) - return -ENOMEM; - - memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op)); - i_op->follow_link = follow_link; - - /* Locking of inode->i_op? - * Since setting i_op is a single word write and they - * are atomic we should be ok here. - */ - inode->i_op = i_op; - return 0; -} - -/** - * sysfs_create_shadow_dir - create a shadow directory for an object. - * @kobj: object we're creating directory for. - * - * sysfs_make_shadowed_dir must already have been called on this - * directory. - */ - -struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) -{ - struct sysfs_dirent *sd; - struct dentry *parent, *dir, *shadow; - struct inode *inode; - - dir = kobj->dentry; - inode = dir->d_inode; - parent = dir->d_parent; - shadow = ERR_PTR(-EINVAL); - if (!sysfs_is_shadowed_inode(inode)) - goto out; - - shadow = d_alloc(parent, &dir->d_name); - if (!shadow) - goto nomem; - - sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR); - if (!sd) - goto nomem; - - d_instantiate(shadow, igrab(inode)); - inc_nlink(inode); - inc_nlink(parent->d_inode); - shadow->d_op = &sysfs_dentry_ops; - - dget(shadow); /* Extra count - pin the dentry in core */ - -out: - return shadow; -nomem: - dput(shadow); - shadow = ERR_PTR(-ENOMEM); - goto out; -} - -/** - * sysfs_remove_shadow_dir - remove an object's directory. - * @shadow: dentry of shadow directory - * - * The only thing special about this is that we remove any files in - * the directory before we remove the directory, and we've inlined - * what used to be sysfs_rmdir() below, instead of calling separately. - */ - -void sysfs_remove_shadow_dir(struct dentry *shadow) -{ - __sysfs_remove_dir(shadow); -} - const struct file_operations sysfs_dir_operations = { .open = sysfs_dir_open, .release = sysfs_dir_close, diff --git a/trunk/fs/sysfs/file.c b/trunk/fs/sysfs/file.c index c0e117649a4d..9cfe53e1e00d 100644 --- a/trunk/fs/sysfs/file.c +++ b/trunk/fs/sysfs/file.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -51,29 +50,17 @@ static struct sysfs_ops subsys_sysfs_ops = { .store = subsys_attr_store, }; -/** - * add_to_collection - add buffer to a collection - * @buffer: buffer to be added - * @node inode of set to add to - */ -static inline void -add_to_collection(struct sysfs_buffer *buffer, struct inode *node) -{ - struct sysfs_buffer_collection *set = node->i_private; +struct sysfs_buffer { + size_t count; + loff_t pos; + char * page; + struct sysfs_ops * ops; + struct semaphore sem; + int needs_read_fill; + int event; +}; - mutex_lock(&node->i_mutex); - list_add(&buffer->associates, &set->associates); - mutex_unlock(&node->i_mutex); -} - -static inline void -remove_from_collection(struct sysfs_buffer *buffer, struct inode *node) -{ - mutex_lock(&node->i_mutex); - list_del(&buffer->associates); - mutex_unlock(&node->i_mutex); -} /** * fill_read_buffer - allocate and fill buffer from object. @@ -83,8 +70,7 @@ remove_from_collection(struct sysfs_buffer *buffer, struct inode *node) * Allocate @buffer->page, if it hasn't been already, then call the * kobject's show() method to fill the buffer with this attribute's * data. - * This is called only once, on the file's first read unless an error - * is returned. + * This is called only once, on the file's first read. */ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) { @@ -102,13 +88,12 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer buffer->event = atomic_read(&sd->s_event); count = ops->show(kobj,attr,buffer->page); + buffer->needs_read_fill = 0; BUG_ON(count > (ssize_t)PAGE_SIZE); - if (count >= 0) { - buffer->needs_read_fill = 0; + if (count >= 0) buffer->count = count; - } else { + else ret = count; - } return ret; } @@ -168,10 +153,6 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) ssize_t retval = 0; down(&buffer->sem); - if (buffer->orphaned) { - retval = -ENODEV; - goto out; - } if (buffer->needs_read_fill) { if ((retval = fill_read_buffer(file->f_path.dentry,buffer))) goto out; @@ -184,6 +165,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) return retval; } + /** * fill_write_buffer - copy buffer from userspace. * @buffer: data buffer for file. @@ -261,25 +243,19 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t ssize_t len; down(&buffer->sem); - if (buffer->orphaned) { - len = -ENODEV; - goto out; - } len = fill_write_buffer(buffer, buf, count); if (len > 0) len = flush_write_buffer(file->f_path.dentry, buffer, len); if (len > 0) *ppos += len; -out: up(&buffer->sem); return len; } -static int sysfs_open_file(struct inode *inode, struct file *file) +static int check_perm(struct inode * inode, struct file * file) { struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); struct attribute * attr = to_attr(file->f_path.dentry); - struct sysfs_buffer_collection *set; struct sysfs_buffer * buffer; struct sysfs_ops * ops = NULL; int error = 0; @@ -309,18 +285,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file) if (!ops) goto Eaccess; - /* make sure we have a collection to add our buffers to */ - mutex_lock(&inode->i_mutex); - if (!(set = inode->i_private)) { - if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) { - error = -ENOMEM; - goto Done; - } else { - INIT_LIST_HEAD(&set->associates); - } - } - mutex_unlock(&inode->i_mutex); - /* File needs write support. * The inode's perms must say it's ok, * and we must have a store method. @@ -346,11 +310,9 @@ static int sysfs_open_file(struct inode *inode, struct file *file) */ buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); if (buffer) { - INIT_LIST_HEAD(&buffer->associates); init_MUTEX(&buffer->sem); buffer->needs_read_fill = 1; buffer->ops = ops; - add_to_collection(buffer, inode); file->private_data = buffer; } else error = -ENOMEM; @@ -363,11 +325,16 @@ static int sysfs_open_file(struct inode *inode, struct file *file) error = -EACCES; module_put(attr->owner); Done: - if (error) + if (error && kobj) kobject_put(kobj); return error; } +static int sysfs_open_file(struct inode * inode, struct file * filp) +{ + return check_perm(inode,filp); +} + static int sysfs_release(struct inode * inode, struct file * filp) { struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent); @@ -375,9 +342,8 @@ static int sysfs_release(struct inode * inode, struct file * filp) struct module * owner = attr->owner; struct sysfs_buffer * buffer = filp->private_data; - if (buffer) - remove_from_collection(buffer, inode); - kobject_put(kobj); + if (kobj) + kobject_put(kobj); /* After this point, attr should not be accessed. */ module_put(owner); @@ -582,7 +548,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) { - sysfs_hash_and_remove(kobj->dentry, attr->name); + sysfs_hash_and_remove(kobj->dentry,attr->name); } diff --git a/trunk/fs/sysfs/group.c b/trunk/fs/sysfs/group.c index b20951c93761..122145b0895c 100644 --- a/trunk/fs/sysfs/group.c +++ b/trunk/fs/sysfs/group.c @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include "sysfs.h" diff --git a/trunk/fs/sysfs/inode.c b/trunk/fs/sysfs/inode.c index 542d2bcc73df..e79e38d52c00 100644 --- a/trunk/fs/sysfs/inode.c +++ b/trunk/fs/sysfs/inode.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "sysfs.h" extern struct super_block * sysfs_sb; @@ -33,16 +32,6 @@ static struct inode_operations sysfs_inode_operations ={ .setattr = sysfs_setattr, }; -void sysfs_delete_inode(struct inode *inode) -{ - /* Free the shadowed directory inode operations */ - if (sysfs_is_shadowed_inode(inode)) { - kfree(inode->i_op); - inode->i_op = NULL; - } - return generic_delete_inode(inode); -} - int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) { struct inode * inode = dentry->d_inode; @@ -220,22 +209,6 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd) return NULL; } -static inline void orphan_all_buffers(struct inode *node) -{ - struct sysfs_buffer_collection *set = node->i_private; - struct sysfs_buffer *buf; - - mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD); - if (node->i_private) { - list_for_each_entry(buf, &set->associates, associates) { - down(&buf->sem); - buf->orphaned = 1; - up(&buf->sem); - } - } - mutex_unlock(&node->i_mutex); -} - /* * Unhashes the dentry corresponding to given sysfs_dirent @@ -244,23 +217,16 @@ static inline void orphan_all_buffers(struct inode *node) void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) { struct dentry * dentry = sd->s_dentry; - struct inode *inode; if (dentry) { spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); if (!(d_unhashed(dentry) && dentry->d_inode)) { - inode = dentry->d_inode; - spin_lock(&inode->i_lock); - __iget(inode); - spin_unlock(&inode->i_lock); dget_locked(dentry); __d_drop(dentry); spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); simple_unlink(parent->d_inode, dentry); - orphan_all_buffers(inode); - iput(inode); } else { spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); @@ -282,7 +248,7 @@ int sysfs_hash_and_remove(struct dentry * dir, const char * name) return -ENOENT; parent_sd = dir->d_fsdata; - mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); + mutex_lock(&dir->d_inode->i_mutex); list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { if (!sd->s_element) continue; diff --git a/trunk/fs/sysfs/mount.c b/trunk/fs/sysfs/mount.c index f6a87a824883..e503f858fba8 100644 --- a/trunk/fs/sysfs/mount.c +++ b/trunk/fs/sysfs/mount.c @@ -8,7 +8,6 @@ #include #include #include -#include #include "sysfs.h" @@ -19,12 +18,9 @@ struct vfsmount *sysfs_mount; struct super_block * sysfs_sb = NULL; struct kmem_cache *sysfs_dir_cachep; -static void sysfs_clear_inode(struct inode *inode); - static struct super_operations sysfs_ops = { .statfs = simple_statfs, - .drop_inode = sysfs_delete_inode, - .clear_inode = sysfs_clear_inode, + .drop_inode = generic_delete_inode, }; static struct sysfs_dirent sysfs_root = { @@ -35,11 +31,6 @@ static struct sysfs_dirent sysfs_root = { .s_iattr = NULL, }; -static void sysfs_clear_inode(struct inode *inode) -{ - kfree(inode->i_private); -} - static int sysfs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; diff --git a/trunk/fs/sysfs/symlink.c b/trunk/fs/sysfs/symlink.c index 4869f611192f..f50e3cc2ded8 100644 --- a/trunk/fs/sysfs/symlink.c +++ b/trunk/fs/sysfs/symlink.c @@ -7,7 +7,6 @@ #include #include #include -#include #include "sysfs.h" diff --git a/trunk/fs/sysfs/sysfs.h b/trunk/fs/sysfs/sysfs.h index fe1cbfd208ed..bd7cec295dab 100644 --- a/trunk/fs/sysfs/sysfs.h +++ b/trunk/fs/sysfs/sysfs.h @@ -2,7 +2,6 @@ extern struct vfsmount * sysfs_mount; extern struct kmem_cache *sysfs_dir_cachep; -extern void sysfs_delete_inode(struct inode *inode); extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); @@ -34,22 +33,6 @@ struct sysfs_symlink { struct kobject * target_kobj; }; -struct sysfs_buffer { - struct list_head associates; - size_t count; - loff_t pos; - char * page; - struct sysfs_ops * ops; - struct semaphore sem; - int orphaned; - int needs_read_fill; - int event; -}; - -struct sysfs_buffer_collection { - struct list_head associates; -}; - static inline struct kobject * to_kobj(struct dentry * dentry) { struct sysfs_dirent * sd = dentry->d_fsdata; @@ -113,7 +96,3 @@ static inline void sysfs_put(struct sysfs_dirent * sd) release_sysfs_dirent(sd); } -static inline int sysfs_is_shadowed_inode(struct inode *inode) -{ - return S_ISDIR(inode->i_mode) && inode->i_op->follow_link; -} diff --git a/trunk/include/asm-alpha/pci.h b/trunk/include/asm-alpha/pci.h index 85aa1127c903..4e115f368d5f 100644 --- a/trunk/include/asm-alpha/pci.h +++ b/trunk/include/asm-alpha/pci.h @@ -293,6 +293,4 @@ struct pci_dev *alpha_gendev_to_pci(struct device *dev); #define IOBASE_ROOT_BUS 5 #define IOBASE_FROM_HOSE 0x10000 -extern struct pci_dev *isa_bridge; - #endif /* __ALPHA_PCI_H */ diff --git a/trunk/include/asm-ia64/machvec.h b/trunk/include/asm-ia64/machvec.h index 3c96ac19154e..a3891eb3f217 100644 --- a/trunk/include/asm-ia64/machvec.h +++ b/trunk/include/asm-ia64/machvec.h @@ -21,7 +21,6 @@ struct mm_struct; struct pci_bus; struct task_struct; struct pci_dev; -struct msi_desc; typedef void ia64_mv_setup_t (char **); typedef void ia64_mv_cpu_init_t (void); @@ -80,7 +79,7 @@ typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *); typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *); typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *); -typedef int ia64_mv_setup_msi_irq_t (struct pci_dev *pdev, struct msi_desc *); +typedef int ia64_mv_setup_msi_irq_t (unsigned int irq, struct pci_dev *pdev); typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq); static inline void diff --git a/trunk/include/linux/Kbuild b/trunk/include/linux/Kbuild index 683513e310de..157db77a7170 100644 --- a/trunk/include/linux/Kbuild +++ b/trunk/include/linux/Kbuild @@ -11,7 +11,6 @@ header-y += netfilter_arp/ header-y += netfilter_bridge/ header-y += netfilter_ipv4/ header-y += netfilter_ipv6/ -header-y += usb/ header-y += affs_hardblocks.h header-y += aio_abi.h @@ -327,6 +326,7 @@ unifdef-y += udp.h unifdef-y += uinput.h unifdef-y += uio.h unifdef-y += unistd.h +unifdef-y += usb_ch9.h unifdef-y += usbdevice_fs.h unifdef-y += user.h unifdef-y += utsname.h diff --git a/trunk/include/linux/device.h b/trunk/include/linux/device.h index 5ca1cdba563a..f44247fe8135 100644 --- a/trunk/include/linux/device.h +++ b/trunk/include/linux/device.h @@ -126,7 +126,6 @@ struct device_driver { struct klist_node knode_bus; struct module * owner; - const char * mod_name; /* used for built-in modules */ int (*probe) (struct device * dev); int (*remove) (struct device * dev); @@ -328,13 +327,6 @@ extern struct class_device *class_device_create(struct class *cls, __attribute__((format(printf,5,6))); extern void class_device_destroy(struct class *cls, dev_t devt); -struct device_type { - struct device_attribute *attrs; - int (*uevent)(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); - void (*release)(struct device *dev); -}; - /* interface for exporting device attributes */ struct device_attribute { struct attribute attr; @@ -363,7 +355,6 @@ struct device { struct kobject kobj; char bus_id[BUS_ID_SIZE]; /* position on parent bus */ - struct device_type *type; unsigned is_registered:1; struct device_attribute uevent_attr; struct device_attribute *devt_attr; @@ -399,10 +390,9 @@ struct device { /* class_device migration path */ struct list_head node; - struct class *class; + struct class *class; /* optional*/ dev_t devt; /* dev_t, creates the sysfs "dev" */ struct attribute_group **groups; /* optional groups */ - int uevent_suppress; void (*release)(struct device * dev); }; diff --git a/trunk/include/linux/hid.h b/trunk/include/linux/hid.h index d26b08f461f2..93173fe45634 100644 --- a/trunk/include/linux/hid.h +++ b/trunk/include/linux/hid.h @@ -266,7 +266,6 @@ struct hid_item { #define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000 #define HID_QUIRK_IGNORE_MOUSE 0x00040000 -#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000 /* * This is the global environment of the parser. This information is diff --git a/trunk/include/linux/ide.h b/trunk/include/linux/ide.h index 04e0fa97ac99..e26a03981a94 100644 --- a/trunk/include/linux/ide.h +++ b/trunk/include/linux/ide.h @@ -18,9 +18,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_IDEACPI -#include -#endif #include #include #include @@ -544,11 +541,6 @@ typedef enum { struct ide_driver_s; struct ide_settings_s; -#ifdef CONFIG_BLK_DEV_IDEACPI -struct ide_acpi_drive_link; -struct ide_acpi_hwif_link; -#endif - typedef struct ide_drive_s { char name[4]; /* drive name, such as "hda" */ char driver_req[10]; /* requests specific driver */ @@ -645,9 +637,6 @@ typedef struct ide_drive_s { int lun; /* logical unit */ int crc_count; /* crc counter to reduce drive speed */ -#ifdef CONFIG_BLK_DEV_IDEACPI - struct ide_acpi_drive_link *acpidata; -#endif struct list_head list; struct device gendev; struct completion gendev_rel_comp; /* to deal with device release() */ @@ -815,10 +804,6 @@ typedef struct hwif_s { void *hwif_data; /* extra hwif data */ unsigned dma; - -#ifdef CONFIG_BLK_DEV_IDEACPI - struct ide_acpi_hwif_link *acpidata; -#endif } ____cacheline_internodealigned_in_smp ide_hwif_t; /* @@ -1207,8 +1192,8 @@ void ide_init_disk(struct gendisk *, ide_drive_t *); extern int ideprobe_init(void); extern void ide_scan_pcibus(int scan_direction) __init; -extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner, const char *mod_name); -#define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE, KBUILD_MODNAME) +extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner); +#define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE) void ide_pci_setup_ports(struct pci_dev *, struct ide_pci_device_s *, int, ata_index_t *); extern void ide_setup_pci_noise (struct pci_dev *dev, struct ide_pci_device_s *d); @@ -1313,18 +1298,6 @@ static inline void ide_dma_verbose(ide_drive_t *drive) { ; } static inline void ide_release_dma(ide_hwif_t *drive) {;} #endif -#ifdef CONFIG_BLK_DEV_IDEACPI -extern int ide_acpi_exec_tfs(ide_drive_t *drive); -extern void ide_acpi_get_timing(ide_hwif_t *hwif); -extern void ide_acpi_push_timing(ide_hwif_t *hwif); -extern void ide_acpi_init(ide_hwif_t *hwif); -#else -static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; } -static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; } -static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; } -static inline void ide_acpi_init(ide_hwif_t *hwif) { ; } -#endif - extern int ide_hwif_request_regions(ide_hwif_t *hwif); extern void ide_hwif_release_regions(ide_hwif_t* hwif); extern void ide_unregister (unsigned int index); diff --git a/trunk/include/linux/irq.h b/trunk/include/linux/irq.h index 5504b671357f..52fc4052a0ae 100644 --- a/trunk/include/linux/irq.h +++ b/trunk/include/linux/irq.h @@ -68,7 +68,6 @@ typedef void fastcall (*irq_flow_handler_t)(unsigned int irq, #define IRQ_MOVE_PENDING 0x40000000 /* need to re-target IRQ destination */ struct proc_dir_entry; -struct msi_desc; /** * struct irq_chip - hardware interrupt chip descriptor @@ -149,7 +148,6 @@ struct irq_chip { struct irq_desc { irq_flow_handler_t handle_irq; struct irq_chip *chip; - struct msi_desc *msi_desc; void *handler_data; void *chip_data; struct irqaction *action; /* IRQ action list */ @@ -375,12 +373,10 @@ extern int set_irq_chip(unsigned int irq, struct irq_chip *chip); extern int set_irq_data(unsigned int irq, void *data); extern int set_irq_chip_data(unsigned int irq, void *data); extern int set_irq_type(unsigned int irq, unsigned int type); -extern int set_irq_msi(unsigned int irq, struct msi_desc *entry); #define get_irq_chip(irq) (irq_desc[irq].chip) #define get_irq_chip_data(irq) (irq_desc[irq].chip_data) #define get_irq_data(irq) (irq_desc[irq].handler_data) -#define get_irq_msi(irq) (irq_desc[irq].msi_desc) #endif /* CONFIG_GENERIC_HARDIRQS */ diff --git a/trunk/include/linux/kobject.h b/trunk/include/linux/kobject.h index b850e0310538..76538fcf2c4e 100644 --- a/trunk/include/linux/kobject.h +++ b/trunk/include/linux/kobject.h @@ -74,13 +74,9 @@ extern void kobject_init(struct kobject *); extern void kobject_cleanup(struct kobject *); extern int __must_check kobject_add(struct kobject *); -extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *); extern void kobject_del(struct kobject *); extern int __must_check kobject_rename(struct kobject *, const char *new_name); -extern int __must_check kobject_shadow_rename(struct kobject *kobj, - struct dentry *new_parent, - const char *new_name); extern int __must_check kobject_move(struct kobject *, struct kobject *); extern int __must_check kobject_register(struct kobject *); diff --git a/trunk/include/linux/module.h b/trunk/include/linux/module.h index 419d3ef293dd..10f771a49997 100644 --- a/trunk/include/linux/module.h +++ b/trunk/include/linux/module.h @@ -58,7 +58,6 @@ struct module_kobject { struct kobject kobj; struct module *mod; - struct kobject *drivers_dir; }; /* These are either module local, or the kernel's dummy ones. */ @@ -264,7 +263,7 @@ struct module struct module_attribute *modinfo_attrs; const char *version; const char *srcversion; - struct kobject *holders_dir; + struct kobject *drivers_dir; /* Exported symbols */ const struct kernel_symbol *syms; diff --git a/trunk/include/linux/msi.h b/trunk/include/linux/msi.h index 74c8a2ecc9dd..c7ef94343673 100644 --- a/trunk/include/linux/msi.h +++ b/trunk/include/linux/msi.h @@ -7,10 +7,11 @@ struct msi_msg { u32 data; /* 16 bits of msi message data */ }; -/* Helper functions */ +/* Heper functions */ extern void mask_msi_irq(unsigned int irq); extern void unmask_msi_irq(unsigned int irq); extern void read_msi_msg(unsigned int irq, struct msi_msg *msg); + extern void write_msi_msg(unsigned int irq, struct msi_msg *msg); struct msi_desc { @@ -41,7 +42,7 @@ struct msi_desc { /* * The arch hook for setup up msi irqs */ -int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc); +int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev); void arch_teardown_msi_irq(unsigned int irq); diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 2e37f5012788..fea0d9db6846 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -529,11 +529,10 @@ struct net_device struct net_bridge_port *br_port; /* class/net/name entry */ - struct device dev; + struct class_device class_dev; /* space for optional statistics and wireless sysfs groups */ struct attribute_group *sysfs_groups[3]; }; -#define to_net_dev(d) container_of(d, struct net_device, dev) #define NETDEV_ALIGN 32 #define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) @@ -549,7 +548,7 @@ static inline void *netdev_priv(struct net_device *dev) /* Set the sysfs physical device reference for the network logical device * if set prior to registration will cause a symlink during initialization. */ -#define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev)) +#define SET_NETDEV_DEV(net, pdev) ((net)->class_dev.dev = (pdev)) struct packet_type { __be16 type; /* This is really htons(ether_type). */ diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index 805412cc6875..f3c617eabd8d 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -174,9 +174,6 @@ struct pci_dev { struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ int rom_attr_enabled; /* has display of the rom attribute been enabled? */ struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ -#ifdef CONFIG_PCI_MSI - unsigned int first_msi_irq; -#endif }; #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list) @@ -184,11 +181,6 @@ struct pci_dev { #define to_pci_dev(n) container_of(n, struct pci_dev, dev) #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) -static inline int pci_channel_offline(struct pci_dev *pdev) -{ - return (pdev->error_state != pci_channel_io_normal); -} - static inline struct pci_cap_saved_state *pci_find_saved_cap( struct pci_dev *pci_dev,char cap) { @@ -471,7 +463,8 @@ extern void pci_sort_breadthfirst(void); /* Generic PCI functions exported to card drivers */ -struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from); +struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from); +struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int device, const struct pci_dev *from); struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); int pci_find_capability (struct pci_dev *dev, int cap); int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap); @@ -540,7 +533,6 @@ void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); int __must_check pci_assign_resource(struct pci_dev *dev, int i); int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i); void pci_restore_bars(struct pci_dev *dev); -int pci_select_bars(struct pci_dev *dev, unsigned long flags); /* ROM control related routines */ void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size); @@ -569,8 +561,6 @@ int __must_check pci_request_regions(struct pci_dev *, const char *); void pci_release_regions(struct pci_dev *); int __must_check pci_request_region(struct pci_dev *, int, const char *); void pci_release_region(struct pci_dev *, int); -int pci_request_selected_regions(struct pci_dev *, int, const char *); -void pci_release_selected_regions(struct pci_dev *, int); /* drivers/pci/bus.c */ int __must_check pci_bus_alloc_resource(struct pci_bus *bus, @@ -583,11 +573,10 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus, void pci_enable_bridges(struct pci_bus *bus); /* Proper probing supporting hot-pluggable devices */ -int __must_check __pci_register_driver(struct pci_driver *, struct module *, - const char *mod_name); +int __must_check __pci_register_driver(struct pci_driver *, struct module *); static inline int __must_check pci_register_driver(struct pci_driver *driver) { - return __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME); + return __pci_register_driver(driver, THIS_MODULE); } void pci_unregister_driver(struct pci_driver *); @@ -622,6 +611,10 @@ enum pci_dma_burst_strategy { strategy_parameter byte boundaries */ }; +#if defined(CONFIG_ISA) || defined(CONFIG_EISA) +extern struct pci_dev *isa_bridge; +#endif + struct msix_entry { u16 vector; /* kernel uses to write allocated vector */ u16 entry; /* driver uses to specify entry, OS writes */ @@ -629,6 +622,7 @@ struct msix_entry { #ifndef CONFIG_PCI_MSI +static inline void pci_scan_msi_device(struct pci_dev *dev) {} static inline int pci_enable_msi(struct pci_dev *dev) {return -1;} static inline void pci_disable_msi(struct pci_dev *dev) {} static inline int pci_enable_msix(struct pci_dev* dev, @@ -636,6 +630,7 @@ static inline int pci_enable_msix(struct pci_dev* dev, static inline void pci_disable_msix(struct pci_dev *dev) {} static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {} #else +extern void pci_scan_msi_device(struct pci_dev *dev); extern int pci_enable_msi(struct pci_dev *dev); extern void pci_disable_msi(struct pci_dev *dev); extern int pci_enable_msix(struct pci_dev* dev, @@ -727,6 +722,8 @@ static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; } static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; } +#define isa_bridge ((struct pci_dev *)NULL) + #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0) static inline void pci_block_user_cfg_access(struct pci_dev *dev) { } diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index defdeed20641..ccd706f876ec 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -1454,7 +1454,6 @@ #define PCI_VENDOR_ID_TOSHIBA_2 0x102f #define PCI_DEVICE_ID_TOSHIBA_TC35815CF 0x0030 -#define PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE 0x0105 #define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108 #define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3 @@ -2071,8 +2070,6 @@ #define PCI_VENDOR_ID_TDI 0x192E #define PCI_DEVICE_ID_TDI_EHCI 0x0101 -#define PCI_VENDOR_ID_PASEMI 0x1959 - #define PCI_VENDOR_ID_JMICRON 0x197B #define PCI_DEVICE_ID_JMICRON_JMB360 0x2360 #define PCI_DEVICE_ID_JMICRON_JMB361 0x2361 diff --git a/trunk/include/linux/serio.h b/trunk/include/linux/serio.h index ac2c70e7f760..0f478a8791a2 100644 --- a/trunk/include/linux/serio.h +++ b/trunk/include/linux/serio.h @@ -86,11 +86,6 @@ static inline void serio_register_port(struct serio *serio) void serio_unregister_port(struct serio *serio); void serio_unregister_child_port(struct serio *serio); -int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name); -static inline int serio_register_driver(struct serio_driver *drv) -{ - return __serio_register_driver(drv, THIS_MODULE, KBUILD_MODNAME); -} int serio_register_driver(struct serio_driver *drv); void serio_unregister_driver(struct serio_driver *drv); diff --git a/trunk/include/linux/spi/spi.h b/trunk/include/linux/spi/spi.h index 8c2edd82a073..176f6e36dbfa 100644 --- a/trunk/include/linux/spi/spi.h +++ b/trunk/include/linux/spi/spi.h @@ -170,7 +170,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * message's completion function when the transaction completes. */ struct spi_master { - struct device dev; + struct class_device cdev; /* other than negative (== assign one dynamically), bus_num is fully * board-specific. usually that simplifies to being SOC-specific. @@ -216,17 +216,17 @@ struct spi_master { static inline void *spi_master_get_devdata(struct spi_master *master) { - return dev_get_drvdata(&master->dev); + return class_get_devdata(&master->cdev); } static inline void spi_master_set_devdata(struct spi_master *master, void *data) { - dev_set_drvdata(&master->dev, data); + class_set_devdata(&master->cdev, data); } static inline struct spi_master *spi_master_get(struct spi_master *master) { - if (!master || !get_device(&master->dev)) + if (!master || !class_device_get(&master->cdev)) return NULL; return master; } @@ -234,7 +234,7 @@ static inline struct spi_master *spi_master_get(struct spi_master *master) static inline void spi_master_put(struct spi_master *master) { if (master) - put_device(&master->dev); + class_device_put(&master->cdev); } diff --git a/trunk/include/linux/sysfs.h b/trunk/include/linux/sysfs.h index 192de3afa96b..2129d1b6c874 100644 --- a/trunk/include/linux/sysfs.h +++ b/trunk/include/linux/sysfs.h @@ -11,12 +11,10 @@ #define _SYSFS_H_ #include -#include #include struct kobject; struct module; -struct nameidata; struct attribute { const char * name; @@ -90,13 +88,13 @@ struct sysfs_dirent { #ifdef CONFIG_SYSFS extern int __must_check -sysfs_create_dir(struct kobject *, struct dentry *); +sysfs_create_dir(struct kobject *); extern void sysfs_remove_dir(struct kobject *); extern int __must_check -sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name); +sysfs_rename_dir(struct kobject *, const char *new_name); extern int __must_check sysfs_move_dir(struct kobject *, struct kobject *); @@ -128,17 +126,11 @@ int __must_check sysfs_create_group(struct kobject *, void sysfs_remove_group(struct kobject *, const struct attribute_group *); void sysfs_notify(struct kobject * k, char *dir, char *attr); - -extern int sysfs_make_shadowed_dir(struct kobject *kobj, - void * (*follow_link)(struct dentry *, struct nameidata *)); -extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj); -extern void sysfs_remove_shadow_dir(struct dentry *dir); - extern int __must_check sysfs_init(void); #else /* CONFIG_SYSFS */ -static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow) +static inline int sysfs_create_dir(struct kobject * k) { return 0; } @@ -148,9 +140,7 @@ static inline void sysfs_remove_dir(struct kobject * k) ; } -static inline int sysfs_rename_dir(struct kobject * k, - struct dentry *new_parent, - const char *new_name) +static inline int sysfs_rename_dir(struct kobject * k, const char *new_name) { return 0; } @@ -214,12 +204,6 @@ static inline void sysfs_notify(struct kobject * k, char *dir, char *attr) { } -static inline int sysfs_make_shadowed_dir(struct kobject *kobj, - void * (*follow_link)(struct dentry *, struct nameidata *)) -{ - return 0; -} - static inline int __must_check sysfs_init(void) { return 0; diff --git a/trunk/include/linux/usb.h b/trunk/include/linux/usb.h index b5c226a87ed8..aab5b1b72021 100644 --- a/trunk/include/linux/usb.h +++ b/trunk/include/linux/usb.h @@ -2,7 +2,7 @@ #define __LINUX_USB_H #include -#include +#include #define USB_MAJOR 180 #define USB_DEVICE_MAJOR 189 @@ -107,8 +107,7 @@ enum usb_interface_condition { * @needs_remote_wakeup: flag set when the driver requires remote-wakeup * capability during autosuspend. * @dev: driver model's view of this device - * @usb_dev: if an interface is bound to the USB major, this will point - * to the sysfs representation for that device. + * @class_dev: driver model's class view of this device. * @pm_usage_cnt: PM usage counter for this interface; autosuspend is not * allowed unless the counter is 0. * @@ -153,7 +152,7 @@ struct usb_interface { unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */ struct device dev; /* interface specific device info */ - struct device *usb_dev; /* pointer to the usb class's device, if any */ + struct class_device *class_dev; int pm_usage_cnt; /* usage counter for autosuspend */ }; #define to_usb_interface(d) container_of(d, struct usb_interface, dev) @@ -373,7 +372,7 @@ struct usb_device { char *serial; /* iSerialNumber string, if present */ struct list_head filelist; - struct device *usbfs_dev; + struct class_device *class_dev; struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ /* @@ -476,8 +475,6 @@ extern void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface); const struct usb_device_id *usb_match_id(struct usb_interface *interface, const struct usb_device_id *id); -extern int usb_match_one_id(struct usb_interface *interface, - const struct usb_device_id *id); extern struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor); @@ -556,18 +553,6 @@ static inline int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *e USB_ENDPOINT_XFER_BULK); } -/** - * usb_endpoint_xfer_control - check if the endpoint has control transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type control, otherwise it returns false. - */ -static inline int usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL); -} - /** * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type * @epd: endpoint to be checked @@ -738,21 +723,11 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor /* ----------------------------------------------------------------------- */ -/* Stuff for dynamic usb ids */ struct usb_dynids { spinlock_t lock; struct list_head list; }; -struct usb_dynid { - struct list_head node; - struct usb_device_id id; -}; - -extern ssize_t usb_store_new_id(struct usb_dynids *dynids, - struct device_driver *driver, - const char *buf, size_t count); - /** * struct usbdrv_wrap - wrapper for driver-model structure * @driver: The driver-model core driver structure. @@ -893,11 +868,10 @@ struct usb_class_driver { * use these in module_init()/module_exit() * and don't forget MODULE_DEVICE_TABLE(usb, ...) */ -extern int usb_register_driver(struct usb_driver *, struct module *, - const char *); +extern int usb_register_driver(struct usb_driver *, struct module *); static inline int usb_register(struct usb_driver *driver) { - return usb_register_driver(driver, THIS_MODULE, KBUILD_MODNAME); + return usb_register_driver(driver, THIS_MODULE); } extern void usb_deregister(struct usb_driver *); @@ -1111,6 +1085,7 @@ struct urb struct kref kref; /* reference count of the URB */ spinlock_t lock; /* lock for the URB */ void *hcpriv; /* private data for host controller */ + int bandwidth; /* bandwidth for INT/ISO request */ atomic_t use_count; /* concurrent submissions counter */ u8 reject; /* submissions will fail */ diff --git a/trunk/include/linux/usb/Kbuild b/trunk/include/linux/usb/Kbuild deleted file mode 100644 index 43f160cfe003..000000000000 --- a/trunk/include/linux/usb/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -unifdef-y += audio.h -unifdef-y += cdc.h -unifdef-y += ch9.h -unifdef-y += midi.h - diff --git a/trunk/include/linux/usb/serial.h b/trunk/include/linux/usb/serial.h index 33dcd8576696..10f99e5f1a97 100644 --- a/trunk/include/linux/usb/serial.h +++ b/trunk/include/linux/usb/serial.h @@ -179,9 +179,6 @@ static inline void usb_set_serial_data (struct usb_serial *serial, void *data) * memory structure allocation at this point in time. * @shutdown: pointer to the driver's shutdown function. This will be * called when the device is removed from the system. - * @usb_driver: pointer to the struct usb_driver that controls this - * device. This is necessary to allow dynamic ids to be added to - * the driver from sysfs. * * This structure is defines a USB Serial driver. It provides all of * the information that the USB serial core code needs. If the function @@ -205,8 +202,6 @@ struct usb_serial_driver { struct list_head driver_list; struct device_driver driver; - struct usb_driver *usb_driver; - struct usb_dynids dynids; int (*probe) (struct usb_serial *serial, const struct usb_device_id *id); int (*attach) (struct usb_serial *serial); diff --git a/trunk/include/linux/usb/ch9.h b/trunk/include/linux/usb_ch9.h similarity index 99% rename from trunk/include/linux/usb/ch9.h rename to trunk/include/linux/usb_ch9.h index ae7833749fa2..c720d107ff29 100644 --- a/trunk/include/linux/usb/ch9.h +++ b/trunk/include/linux/usb_ch9.h @@ -224,7 +224,6 @@ struct usb_device_descriptor { #define USB_CLASS_CONTENT_SEC 0x0d /* content security */ #define USB_CLASS_VIDEO 0x0e #define USB_CLASS_WIRELESS_CONTROLLER 0xe0 -#define USB_CLASS_MISC 0xef #define USB_CLASS_APP_SPEC 0xfe #define USB_CLASS_VENDOR_SPEC 0xff diff --git a/trunk/include/linux/usb_gadgetfs.h b/trunk/include/linux/usb_gadgetfs.h index 8086d5a9b94e..b53d6ae8e55e 100644 --- a/trunk/include/linux/usb_gadgetfs.h +++ b/trunk/include/linux/usb_gadgetfs.h @@ -2,7 +2,7 @@ #include #include -#include +#include /* * Filesystem based user-mode API to USB Gadget controller hardware diff --git a/trunk/include/pcmcia/ss.h b/trunk/include/pcmcia/ss.h index 6e84258b94de..623a0fc0dae1 100644 --- a/trunk/include/pcmcia/ss.h +++ b/trunk/include/pcmcia/ss.h @@ -284,7 +284,7 @@ struct pcmcia_socket { #endif /* socket device */ - struct device dev; + struct class_device dev; void *driver_data; /* data internal to the socket driver */ }; diff --git a/trunk/kernel/irq/chip.c b/trunk/kernel/irq/chip.c index 475e8a71bcdc..d27b25855743 100644 --- a/trunk/kernel/irq/chip.c +++ b/trunk/kernel/irq/chip.c @@ -39,7 +39,6 @@ void dynamic_irq_init(unsigned int irq) desc->chip = &no_irq_chip; desc->handle_irq = handle_bad_irq; desc->depth = 1; - desc->msi_desc = NULL; desc->handler_data = NULL; desc->chip_data = NULL; desc->action = NULL; @@ -75,9 +74,6 @@ void dynamic_irq_cleanup(unsigned int irq) WARN_ON(1); return; } - desc->msi_desc = NULL; - desc->handler_data = NULL; - desc->chip_data = NULL; desc->handle_irq = handle_bad_irq; desc->chip = &no_irq_chip; spin_unlock_irqrestore(&desc->lock, flags); @@ -165,30 +161,6 @@ int set_irq_data(unsigned int irq, void *data) } EXPORT_SYMBOL(set_irq_data); -/** - * set_irq_data - set irq type data for an irq - * @irq: Interrupt number - * @data: Pointer to interrupt specific data - * - * Set the hardware irq controller data for an irq - */ -int set_irq_msi(unsigned int irq, struct msi_desc *entry) -{ - struct irq_desc *desc; - unsigned long flags; - - if (irq >= NR_IRQS) { - printk(KERN_ERR - "Trying to install msi data for IRQ%d\n", irq); - return -EINVAL; - } - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock, flags); - desc->msi_desc = entry; - spin_unlock_irqrestore(&desc->lock, flags); - return 0; -} - /** * set_irq_chip_data - set irq chip data for an irq * @irq: Interrupt number diff --git a/trunk/kernel/module.c b/trunk/kernel/module.c index 8a94e054230c..d0f2260a0210 100644 --- a/trunk/kernel/module.c +++ b/trunk/kernel/module.c @@ -537,8 +537,6 @@ static int already_uses(struct module *a, struct module *b) static int use_module(struct module *a, struct module *b) { struct module_use *use; - int no_warn; - if (b == NULL || already_uses(a, b)) return 1; if (!strong_try_module_get(b)) @@ -554,7 +552,6 @@ static int use_module(struct module *a, struct module *b) use->module_which_uses = a; list_add(&use->list, &b->modules_which_use_me); - no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); return 1; } @@ -572,7 +569,6 @@ static void module_unload_free(struct module *mod) module_put(i); list_del(&use->list); kfree(use); - sysfs_remove_link(i->holders_dir, mod->name); /* There can be at most one match. */ break; } @@ -1110,7 +1106,9 @@ static void module_remove_modinfo_attrs(struct module *mod) kfree(mod->modinfo_attrs); } -static int mod_sysfs_init(struct module *mod) +static int mod_sysfs_setup(struct module *mod, + struct kernel_param *kparam, + unsigned int num_params) { int err; @@ -1127,30 +1125,21 @@ static int mod_sysfs_init(struct module *mod) kobj_set_kset_s(&mod->mkobj, module_subsys); mod->mkobj.mod = mod; - kobject_init(&mod->mkobj.kobj); - -out: - return err; -} - -static int mod_sysfs_setup(struct module *mod, - struct kernel_param *kparam, - unsigned int num_params) -{ - int err; - /* delay uevent until full sysfs population */ + kobject_init(&mod->mkobj.kobj); err = kobject_add(&mod->mkobj.kobj); if (err) goto out; - mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders"); - if (!mod->holders_dir) + mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers"); + if (!mod->drivers_dir) { + err = -ENOMEM; goto out_unreg; + } err = module_param_sysfs_setup(mod, kparam, num_params); if (err) - goto out_unreg_holders; + goto out_unreg_drivers; err = module_add_modinfo_attrs(mod); if (err) @@ -1161,8 +1150,8 @@ static int mod_sysfs_setup(struct module *mod, out_unreg_param: module_param_sysfs_remove(mod); -out_unreg_holders: - kobject_unregister(mod->holders_dir); +out_unreg_drivers: + kobject_unregister(mod->drivers_dir); out_unreg: kobject_del(&mod->mkobj.kobj); kobject_put(&mod->mkobj.kobj); @@ -1174,10 +1163,7 @@ static void mod_kobject_remove(struct module *mod) { module_remove_modinfo_attrs(mod); module_param_sysfs_remove(mod); - if (mod->mkobj.drivers_dir) - kobject_unregister(mod->mkobj.drivers_dir); - if (mod->holders_dir) - kobject_unregister(mod->holders_dir); + kobject_unregister(mod->drivers_dir); kobject_unregister(&mod->mkobj.kobj); } @@ -1782,10 +1768,6 @@ static struct module *load_module(void __user *umod, /* Now we've moved module, initialize linked lists, etc. */ module_unload_init(mod); - /* Initialize kobject, so we can reference it. */ - if (mod_sysfs_init(mod) != 0) - goto cleanup; - /* Set up license info based on the info section */ set_license(mod, get_modinfo(sechdrs, infoindex, "license")); @@ -2358,43 +2340,19 @@ static char *make_driver_name(struct device_driver *drv) return driver_name; } -static void module_create_drivers_dir(struct module_kobject *mk) -{ - if (!mk || mk->drivers_dir) - return; - - mk->drivers_dir = kobject_add_dir(&mk->kobj, "drivers"); -} - void module_add_driver(struct module *mod, struct device_driver *drv) { char *driver_name; int no_warn; - struct module_kobject *mk = NULL; - - if (!drv) - return; - - if (mod) - mk = &mod->mkobj; - else if (drv->mod_name) { - struct kobject *mkobj; - - /* Lookup built-in module entry in /sys/modules */ - mkobj = kset_find_obj(&module_subsys.kset, drv->mod_name); - if (mkobj) - mk = container_of(mkobj, struct module_kobject, kobj); - } - if (!mk) + if (!mod || !drv) return; /* Don't check return codes; these calls are idempotent */ - no_warn = sysfs_create_link(&drv->kobj, &mk->kobj, "module"); + no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module"); driver_name = make_driver_name(drv); if (driver_name) { - module_create_drivers_dir(mk); - no_warn = sysfs_create_link(mk->drivers_dir, &drv->kobj, + no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj, driver_name); kfree(driver_name); } @@ -2409,10 +2367,10 @@ void module_remove_driver(struct device_driver *drv) return; sysfs_remove_link(&drv->kobj, "module"); - if (drv->owner && drv->owner->mkobj.drivers_dir) { + if (drv->owner && drv->owner->drivers_dir) { driver_name = make_driver_name(drv); if (driver_name) { - sysfs_remove_link(drv->owner->mkobj.drivers_dir, + sysfs_remove_link(drv->owner->drivers_dir, driver_name); kfree(driver_name); } diff --git a/trunk/kernel/params.c b/trunk/kernel/params.c index 553cf7d6a4be..718945da8f58 100644 --- a/trunk/kernel/params.c +++ b/trunk/kernel/params.c @@ -30,8 +30,6 @@ #define DEBUGP(fmt, a...) #endif -static struct kobj_type module_ktype; - static inline char dash2underscore(char c) { if (c == '-') @@ -563,11 +561,14 @@ static void __init kernel_param_sysfs_setup(const char *name, mk->mod = THIS_MODULE; kobj_set_kset_s(mk, module_subsys); kobject_set_name(&mk->kobj, name); - kobject_init(&mk->kobj); - ret = kobject_add(&mk->kobj); + ret = kobject_register(&mk->kobj); BUG_ON(ret < 0); - param_sysfs_setup(mk, kparam, num_params, name_skip); - kobject_uevent(&mk->kobj, KOBJ_ADD); + + /* no need to keep the kobject if no parameter is exported */ + if (!param_sysfs_setup(mk, kparam, num_params, name_skip)) { + kobject_unregister(&mk->kobj); + kfree(mk); + } } /* @@ -673,19 +674,6 @@ static struct sysfs_ops module_sysfs_ops = { .store = module_attr_store, }; -static int uevent_filter(struct kset *kset, struct kobject *kobj) -{ - struct kobj_type *ktype = get_ktype(kobj); - - if (ktype == &module_ktype) - return 1; - return 0; -} - -static struct kset_uevent_ops module_uevent_ops = { - .filter = uevent_filter, -}; - #else static struct sysfs_ops module_sysfs_ops = { .show = NULL, @@ -697,7 +685,7 @@ static struct kobj_type module_ktype = { .sysfs_ops = &module_sysfs_ops, }; -decl_subsys(module, &module_ktype, &module_uevent_ops); +decl_subsys(module, &module_ktype, NULL); /* * param_sysfs_init - wrapper for built-in params support diff --git a/trunk/lib/kobject.c b/trunk/lib/kobject.c index c2917ffe8bf1..7ce6dc138e90 100644 --- a/trunk/lib/kobject.c +++ b/trunk/lib/kobject.c @@ -44,11 +44,11 @@ static int populate_dir(struct kobject * kobj) return error; } -static int create_dir(struct kobject * kobj, struct dentry *shadow_parent) +static int create_dir(struct kobject * kobj) { int error = 0; if (kobject_name(kobj)) { - error = sysfs_create_dir(kobj, shadow_parent); + error = sysfs_create_dir(kobj); if (!error) { if ((error = populate_dir(kobj))) sysfs_remove_dir(kobj); @@ -126,8 +126,6 @@ EXPORT_SYMBOL_GPL(kobject_get_path); */ void kobject_init(struct kobject * kobj) { - if (!kobj) - return; kref_init(&kobj->kref); INIT_LIST_HEAD(&kobj->entry); init_waitqueue_head(&kobj->poll); @@ -158,10 +156,9 @@ static void unlink(struct kobject * kobj) /** * kobject_add - add an object to the hierarchy. * @kobj: object. - * @shadow_parent: sysfs directory to add to. */ -int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) +int kobject_add(struct kobject * kobj) { int error = 0; struct kobject * parent; @@ -192,11 +189,12 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) } kobj->parent = parent; - error = create_dir(kobj, shadow_parent); + error = create_dir(kobj); if (error) { /* unlink does the kobject_put() for us */ unlink(kobj); - kobject_put(parent); + if (parent) + kobject_put(parent); /* be noisy on error issues */ if (error == -EEXIST) @@ -213,15 +211,6 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) return error; } -/** - * kobject_add - add an object to the hierarchy. - * @kobj: object. - */ -int kobject_add(struct kobject * kobj) -{ - return kobject_shadow_add(kobj, NULL); -} - /** * kobject_register - initialize and add an object. @@ -314,29 +303,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name) kobj = kobject_get(kobj); if (!kobj) return -EINVAL; - if (!kobj->parent) - return -EINVAL; - error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name); - kobject_put(kobj); - - return error; -} - -/** - * kobject_rename - change the name of an object - * @kobj: object in question. - * @new_name: object's new name - */ - -int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent, - const char *new_name) -{ - int error = 0; - - kobj = kobject_get(kobj); - if (!kobj) - return -EINVAL; - error = sysfs_rename_dir(kobj, new_parent, new_name); + error = sysfs_rename_dir(kobj, new_name); kobject_put(kobj); return error; @@ -345,7 +312,7 @@ int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent, /** * kobject_move - move object to another parent * @kobj: object in question. - * @new_parent: object's new parent (can be NULL) + * @new_parent: object's new parent */ int kobject_move(struct kobject *kobj, struct kobject *new_parent) @@ -361,8 +328,8 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent) return -EINVAL; new_parent = kobject_get(new_parent); if (!new_parent) { - if (kobj->kset) - new_parent = kobject_get(&kobj->kset->kobj); + error = -EINVAL; + goto out; } /* old object path */ devpath = kobject_get_path(kobj, GFP_KERNEL); @@ -399,8 +366,6 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent) void kobject_del(struct kobject * kobj) { - if (!kobj) - return; sysfs_remove_dir(kobj); unlink(kobj); } @@ -412,8 +377,6 @@ void kobject_del(struct kobject * kobj) void kobject_unregister(struct kobject * kobj) { - if (!kobj) - return; pr_debug("kobject %s: unregistering\n",kobject_name(kobj)); kobject_uevent(kobj, KOBJ_REMOVE); kobject_del(kobj); @@ -451,7 +414,8 @@ void kobject_cleanup(struct kobject * kobj) t->release(kobj); if (s) kset_put(s); - kobject_put(parent); + if (parent) + kobject_put(parent); } static void kobject_release(struct kref *kref) @@ -559,8 +523,6 @@ int kset_add(struct kset * k) int kset_register(struct kset * k) { - if (!k) - return -EINVAL; kset_init(k); return kset_add(k); } @@ -573,8 +535,6 @@ int kset_register(struct kset * k) void kset_unregister(struct kset * k) { - if (!k) - return; kobject_unregister(&k->kobj); } @@ -626,9 +586,6 @@ int subsystem_register(struct subsystem * s) { int error; - if (!s) - return -EINVAL; - subsystem_init(s); pr_debug("subsystem %s: registering\n",s->kset.kobj.name); @@ -641,8 +598,6 @@ int subsystem_register(struct subsystem * s) void subsystem_unregister(struct subsystem * s) { - if (!s) - return; pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name); kset_unregister(&s->kset); } @@ -657,10 +612,6 @@ void subsystem_unregister(struct subsystem * s) int subsys_create_file(struct subsystem * s, struct subsys_attribute * a) { int error = 0; - - if (!s || !a) - return -EINVAL; - if (subsys_get(s)) { error = sysfs_create_file(&s->kset.kobj,&a->attr); subsys_put(s); diff --git a/trunk/net/bridge/br_if.c b/trunk/net/bridge/br_if.c index 2b7c2c7dad48..55bb2634c088 100644 --- a/trunk/net/bridge/br_if.c +++ b/trunk/net/bridge/br_if.c @@ -286,7 +286,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, kobject_init(&p->kobj); kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR); p->kobj.ktype = &brport_ktype; - p->kobj.parent = &(dev->dev.kobj); + p->kobj.parent = &(dev->class_dev.kobj); p->kobj.kset = NULL; return p; diff --git a/trunk/net/bridge/br_sysfs_br.c b/trunk/net/bridge/br_sysfs_br.c index ce10464716a7..de9d1a9473f2 100644 --- a/trunk/net/bridge/br_sysfs_br.c +++ b/trunk/net/bridge/br_sysfs_br.c @@ -21,17 +21,18 @@ #include "br_private.h" -#define to_dev(obj) container_of(obj, struct device, kobj) +#define to_class_dev(obj) container_of(obj,struct class_device,kobj) +#define to_net_dev(class) container_of(class, struct net_device, class_dev) #define to_bridge(cd) ((struct net_bridge *)(to_net_dev(cd)->priv)) /* * Common code for storing bridge parameters. */ -static ssize_t store_bridge_parm(struct device *d, +static ssize_t store_bridge_parm(struct class_device *cd, const char *buf, size_t len, void (*set)(struct net_bridge *, unsigned long)) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); char *endp; unsigned long val; @@ -49,10 +50,9 @@ static ssize_t store_bridge_parm(struct device *d, } -static ssize_t show_forward_delay(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t show_forward_delay(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); } @@ -64,20 +64,18 @@ static void set_forward_delay(struct net_bridge *br, unsigned long val) br->bridge_forward_delay = delay; } -static ssize_t store_forward_delay(struct device *d, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_forward_delay(struct class_device *cd, const char *buf, + size_t len) { - return store_bridge_parm(d, buf, len, set_forward_delay); + return store_bridge_parm(cd, buf, len, set_forward_delay); } -static DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR, - show_forward_delay, store_forward_delay); +static CLASS_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR, + show_forward_delay, store_forward_delay); -static ssize_t show_hello_time(struct device *d, struct device_attribute *attr, - char *buf) +static ssize_t show_hello_time(struct class_device *cd, char *buf) { return sprintf(buf, "%lu\n", - jiffies_to_clock_t(to_bridge(d)->hello_time)); + jiffies_to_clock_t(to_bridge(cd)->hello_time)); } static void set_hello_time(struct net_bridge *br, unsigned long val) @@ -88,20 +86,19 @@ static void set_hello_time(struct net_bridge *br, unsigned long val) br->bridge_hello_time = t; } -static ssize_t store_hello_time(struct device *d, - struct device_attribute *attr, const char *buf, +static ssize_t store_hello_time(struct class_device *cd, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, set_hello_time); + return store_bridge_parm(cd, buf, len, set_hello_time); } -static DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time, - store_hello_time); -static ssize_t show_max_age(struct device *d, struct device_attribute *attr, - char *buf) +static CLASS_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time, + store_hello_time); + +static ssize_t show_max_age(struct class_device *cd, char *buf) { return sprintf(buf, "%lu\n", - jiffies_to_clock_t(to_bridge(d)->max_age)); + jiffies_to_clock_t(to_bridge(cd)->max_age)); } static void set_max_age(struct net_bridge *br, unsigned long val) @@ -112,17 +109,18 @@ static void set_max_age(struct net_bridge *br, unsigned long val) br->bridge_max_age = t; } -static ssize_t store_max_age(struct device *d, struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_max_age(struct class_device *cd, const char *buf, + size_t len) { - return store_bridge_parm(d, buf, len, set_max_age); + return store_bridge_parm(cd, buf, len, set_max_age); } -static DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age); -static ssize_t show_ageing_time(struct device *d, - struct device_attribute *attr, char *buf) +static CLASS_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, + store_max_age); + +static ssize_t show_ageing_time(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time)); } @@ -131,19 +129,17 @@ static void set_ageing_time(struct net_bridge *br, unsigned long val) br->ageing_time = clock_t_to_jiffies(val); } -static ssize_t store_ageing_time(struct device *d, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_ageing_time(struct class_device *cd, const char *buf, + size_t len) { - return store_bridge_parm(d, buf, len, set_ageing_time); + return store_bridge_parm(cd, buf, len, set_ageing_time); } -static DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time, - store_ageing_time); -static ssize_t show_stp_state(struct device *d, - struct device_attribute *attr, char *buf) +static CLASS_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time, + store_ageing_time); +static ssize_t show_stp_state(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%d\n", br->stp_enabled); } @@ -152,19 +148,18 @@ static void set_stp_state(struct net_bridge *br, unsigned long val) br->stp_enabled = val; } -static ssize_t store_stp_state(struct device *d, - struct device_attribute *attr, const char *buf, - size_t len) +static ssize_t store_stp_state(struct class_device *cd, + const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, set_stp_state); + return store_bridge_parm(cd, buf, len, set_stp_state); } -static DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state, - store_stp_state); -static ssize_t show_priority(struct device *d, struct device_attribute *attr, - char *buf) +static CLASS_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state, + store_stp_state); + +static ssize_t show_priority(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%d\n", (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]); } @@ -174,107 +169,92 @@ static void set_priority(struct net_bridge *br, unsigned long val) br_stp_set_bridge_priority(br, (u16) val); } -static ssize_t store_priority(struct device *d, struct device_attribute *attr, +static ssize_t store_priority(struct class_device *cd, const char *buf, size_t len) { - return store_bridge_parm(d, buf, len, set_priority); + return store_bridge_parm(cd, buf, len, set_priority); } -static DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority); +static CLASS_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, + store_priority); -static ssize_t show_root_id(struct device *d, struct device_attribute *attr, - char *buf) +static ssize_t show_root_id(struct class_device *cd, char *buf) { - return br_show_bridge_id(buf, &to_bridge(d)->designated_root); + return br_show_bridge_id(buf, &to_bridge(cd)->designated_root); } -static DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL); +static CLASS_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL); -static ssize_t show_bridge_id(struct device *d, struct device_attribute *attr, - char *buf) +static ssize_t show_bridge_id(struct class_device *cd, char *buf) { - return br_show_bridge_id(buf, &to_bridge(d)->bridge_id); + return br_show_bridge_id(buf, &to_bridge(cd)->bridge_id); } -static DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL); +static CLASS_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL); -static ssize_t show_root_port(struct device *d, struct device_attribute *attr, - char *buf) +static ssize_t show_root_port(struct class_device *cd, char *buf) { - return sprintf(buf, "%d\n", to_bridge(d)->root_port); + return sprintf(buf, "%d\n", to_bridge(cd)->root_port); } -static DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL); +static CLASS_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL); -static ssize_t show_root_path_cost(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t show_root_path_cost(struct class_device *cd, char *buf) { - return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost); + return sprintf(buf, "%d\n", to_bridge(cd)->root_path_cost); } -static DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL); +static CLASS_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL); -static ssize_t show_topology_change(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t show_topology_change(struct class_device *cd, char *buf) { - return sprintf(buf, "%d\n", to_bridge(d)->topology_change); + return sprintf(buf, "%d\n", to_bridge(cd)->topology_change); } -static DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL); +static CLASS_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL); -static ssize_t show_topology_change_detected(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t show_topology_change_detected(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%d\n", br->topology_change_detected); } -static DEVICE_ATTR(topology_change_detected, S_IRUGO, - show_topology_change_detected, NULL); +static CLASS_DEVICE_ATTR(topology_change_detected, S_IRUGO, show_topology_change_detected, NULL); -static ssize_t show_hello_timer(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t show_hello_timer(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer)); } -static DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL); +static CLASS_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL); -static ssize_t show_tcn_timer(struct device *d, struct device_attribute *attr, - char *buf) +static ssize_t show_tcn_timer(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer)); } -static DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL); +static CLASS_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL); -static ssize_t show_topology_change_timer(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t show_topology_change_timer(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer)); } -static DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer, - NULL); +static CLASS_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer, NULL); -static ssize_t show_gc_timer(struct device *d, struct device_attribute *attr, - char *buf) +static ssize_t show_gc_timer(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%ld\n", br_timer_value(&br->gc_timer)); } -static DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL); +static CLASS_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL); -static ssize_t show_group_addr(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t show_group_addr(struct class_device *cd, char *buf) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); return sprintf(buf, "%x:%x:%x:%x:%x:%x\n", br->group_addr[0], br->group_addr[1], br->group_addr[2], br->group_addr[3], br->group_addr[4], br->group_addr[5]); } -static ssize_t store_group_addr(struct device *d, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_group_addr(struct class_device *cd, const char *buf, + size_t len) { - struct net_bridge *br = to_bridge(d); + struct net_bridge *br = to_bridge(cd); unsigned new_addr[6]; int i; @@ -306,28 +286,28 @@ static ssize_t store_group_addr(struct device *d, return len; } -static DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR, - show_group_addr, store_group_addr); +static CLASS_DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR, + show_group_addr, store_group_addr); static struct attribute *bridge_attrs[] = { - &dev_attr_forward_delay.attr, - &dev_attr_hello_time.attr, - &dev_attr_max_age.attr, - &dev_attr_ageing_time.attr, - &dev_attr_stp_state.attr, - &dev_attr_priority.attr, - &dev_attr_bridge_id.attr, - &dev_attr_root_id.attr, - &dev_attr_root_path_cost.attr, - &dev_attr_root_port.attr, - &dev_attr_topology_change.attr, - &dev_attr_topology_change_detected.attr, - &dev_attr_hello_timer.attr, - &dev_attr_tcn_timer.attr, - &dev_attr_topology_change_timer.attr, - &dev_attr_gc_timer.attr, - &dev_attr_group_addr.attr, + &class_device_attr_forward_delay.attr, + &class_device_attr_hello_time.attr, + &class_device_attr_max_age.attr, + &class_device_attr_ageing_time.attr, + &class_device_attr_stp_state.attr, + &class_device_attr_priority.attr, + &class_device_attr_bridge_id.attr, + &class_device_attr_root_id.attr, + &class_device_attr_root_path_cost.attr, + &class_device_attr_root_port.attr, + &class_device_attr_topology_change.attr, + &class_device_attr_topology_change_detected.attr, + &class_device_attr_hello_timer.attr, + &class_device_attr_tcn_timer.attr, + &class_device_attr_topology_change_timer.attr, + &class_device_attr_gc_timer.attr, + &class_device_attr_group_addr.attr, NULL }; @@ -345,8 +325,8 @@ static struct attribute_group bridge_group = { static ssize_t brforward_read(struct kobject *kobj, char *buf, loff_t off, size_t count) { - struct device *dev = to_dev(kobj); - struct net_bridge *br = to_bridge(dev); + struct class_device *cdev = to_class_dev(kobj); + struct net_bridge *br = to_bridge(cdev); int n; /* must read whole records */ @@ -383,7 +363,7 @@ static struct bin_attribute bridge_forward = { */ int br_sysfs_addbr(struct net_device *dev) { - struct kobject *brobj = &dev->dev.kobj; + struct kobject *brobj = &dev->class_dev.kobj; struct net_bridge *br = netdev_priv(dev); int err; @@ -415,9 +395,9 @@ int br_sysfs_addbr(struct net_device *dev) } return 0; out3: - sysfs_remove_bin_file(&dev->dev.kobj, &bridge_forward); + sysfs_remove_bin_file(&dev->class_dev.kobj, &bridge_forward); out2: - sysfs_remove_group(&dev->dev.kobj, &bridge_group); + sysfs_remove_group(&dev->class_dev.kobj, &bridge_group); out1: return err; @@ -425,7 +405,7 @@ int br_sysfs_addbr(struct net_device *dev) void br_sysfs_delbr(struct net_device *dev) { - struct kobject *kobj = &dev->dev.kobj; + struct kobject *kobj = &dev->class_dev.kobj; struct net_bridge *br = netdev_priv(dev); kobject_unregister(&br->ifobj); diff --git a/trunk/net/bridge/br_sysfs_if.c b/trunk/net/bridge/br_sysfs_if.c index 0bc2aef8f9f3..c51c9e42aeb3 100644 --- a/trunk/net/bridge/br_sysfs_if.c +++ b/trunk/net/bridge/br_sysfs_if.c @@ -211,7 +211,7 @@ int br_sysfs_addif(struct net_bridge_port *p) struct brport_attribute **a; int err; - err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj, + err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj, SYSFS_BRIDGE_PORT_LINK); if (err) goto out2; diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 455d589683e8..e660cb57e42a 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -751,7 +751,7 @@ int dev_change_name(struct net_device *dev, char *newname) else strlcpy(dev->name, newname, IFNAMSIZ); - err = device_rename(&dev->dev, dev->name); + err = class_device_rename(&dev->class_dev, dev->name); if (!err) { hlist_del(&dev->name_hlist); hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); @@ -3221,8 +3221,8 @@ void free_netdev(struct net_device *dev) BUG_ON(dev->reg_state != NETREG_UNREGISTERED); dev->reg_state = NETREG_RELEASED; - /* will free via device release */ - put_device(&dev->dev); + /* will free via class release */ + class_device_put(&dev->class_dev); #else kfree((char *)dev - dev->padded); #endif diff --git a/trunk/net/core/net-sysfs.c b/trunk/net/core/net-sysfs.c index 44db095a8f7e..f47f319bb7dc 100644 --- a/trunk/net/core/net-sysfs.c +++ b/trunk/net/core/net-sysfs.c @@ -18,6 +18,9 @@ #include #include +#define to_class_dev(obj) container_of(obj,struct class_device,kobj) +#define to_net_dev(class) container_of(class, struct net_device, class_dev) + static const char fmt_hex[] = "%#x\n"; static const char fmt_long_hex[] = "%#lx\n"; static const char fmt_dec[] = "%d\n"; @@ -29,11 +32,10 @@ static inline int dev_isalive(const struct net_device *dev) } /* use same locking rules as GIF* ioctl's */ -static ssize_t netdev_show(const struct device *dev, - struct device_attribute *attr, char *buf, +static ssize_t netdev_show(const struct class_device *cd, char *buf, ssize_t (*format)(const struct net_device *, char *)) { - struct net_device *net = to_net_dev(dev); + struct net_device *net = to_net_dev(cd); ssize_t ret = -EINVAL; read_lock(&dev_base_lock); @@ -50,15 +52,14 @@ static ssize_t format_##field(const struct net_device *net, char *buf) \ { \ return sprintf(buf, format_string, net->field); \ } \ -static ssize_t show_##field(struct device *dev, \ - struct device_attribute *attr, char *buf) \ +static ssize_t show_##field(struct class_device *cd, char *buf) \ { \ - return netdev_show(dev, attr, buf, format_##field); \ + return netdev_show(cd, buf, format_##field); \ } /* use same locking and permission rules as SIF* ioctl's */ -static ssize_t netdev_store(struct device *dev, struct device_attribute *attr, +static ssize_t netdev_store(struct class_device *dev, const char *buf, size_t len, int (*set)(struct net_device *, unsigned long)) { @@ -103,8 +104,7 @@ static ssize_t format_addr(char *buf, const unsigned char *addr, int len) return cp - buf; } -static ssize_t show_address(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t show_address(struct class_device *dev, char *buf) { struct net_device *net = to_net_dev(dev); ssize_t ret = -EINVAL; @@ -116,8 +116,7 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr, return ret; } -static ssize_t show_broadcast(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_broadcast(struct class_device *dev, char *buf) { struct net_device *net = to_net_dev(dev); if (dev_isalive(net)) @@ -125,8 +124,7 @@ static ssize_t show_broadcast(struct device *dev, return -EINVAL; } -static ssize_t show_carrier(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_carrier(struct class_device *dev, char *buf) { struct net_device *netdev = to_net_dev(dev); if (netif_running(netdev)) { @@ -135,8 +133,7 @@ static ssize_t show_carrier(struct device *dev, return -EINVAL; } -static ssize_t show_dormant(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_dormant(struct class_device *dev, char *buf) { struct net_device *netdev = to_net_dev(dev); @@ -156,8 +153,7 @@ static const char *operstates[] = { "up" }; -static ssize_t show_operstate(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_operstate(struct class_device *dev, char *buf) { const struct net_device *netdev = to_net_dev(dev); unsigned char operstate; @@ -182,10 +178,9 @@ static int change_mtu(struct net_device *net, unsigned long new_mtu) return dev_set_mtu(net, (int) new_mtu); } -static ssize_t store_mtu(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len) { - return netdev_store(dev, attr, buf, len, change_mtu); + return netdev_store(dev, buf, len, change_mtu); } NETDEVICE_SHOW(flags, fmt_hex); @@ -195,10 +190,9 @@ static int change_flags(struct net_device *net, unsigned long new_flags) return dev_change_flags(net, (unsigned) new_flags); } -static ssize_t store_flags(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len) { - return netdev_store(dev, attr, buf, len, change_flags); + return netdev_store(dev, buf, len, change_flags); } NETDEVICE_SHOW(tx_queue_len, fmt_ulong); @@ -209,11 +203,9 @@ static int change_tx_queue_len(struct net_device *net, unsigned long new_len) return 0; } -static ssize_t store_tx_queue_len(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, size_t len) { - return netdev_store(dev, attr, buf, len, change_tx_queue_len); + return netdev_store(dev, buf, len, change_tx_queue_len); } NETDEVICE_SHOW(weight, fmt_dec); @@ -224,13 +216,12 @@ static int change_weight(struct net_device *net, unsigned long new_weight) return 0; } -static ssize_t store_weight(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t store_weight(struct class_device *dev, const char *buf, size_t len) { - return netdev_store(dev, attr, buf, len, change_weight); + return netdev_store(dev, buf, len, change_weight); } -static struct device_attribute net_class_attributes[] = { +static struct class_device_attribute net_class_attributes[] = { __ATTR(addr_len, S_IRUGO, show_addr_len, NULL), __ATTR(iflink, S_IRUGO, show_iflink, NULL), __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), @@ -251,11 +242,10 @@ static struct device_attribute net_class_attributes[] = { }; /* Show a given an attribute in the statistics group */ -static ssize_t netstat_show(const struct device *d, - struct device_attribute *attr, char *buf, +static ssize_t netstat_show(const struct class_device *cd, char *buf, unsigned long offset) { - struct net_device *dev = to_net_dev(d); + struct net_device *dev = to_net_dev(cd); struct net_device_stats *stats; ssize_t ret = -EINVAL; @@ -275,13 +265,12 @@ static ssize_t netstat_show(const struct device *d, /* generate a read-only statistics attribute */ #define NETSTAT_ENTRY(name) \ -static ssize_t show_##name(struct device *d, \ - struct device_attribute *attr, char *buf) \ +static ssize_t show_##name(struct class_device *cd, char *buf) \ { \ - return netstat_show(d, attr, buf, \ + return netstat_show(cd, buf, \ offsetof(struct net_device_stats, name)); \ } \ -static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) +static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) NETSTAT_ENTRY(rx_packets); NETSTAT_ENTRY(tx_packets); @@ -308,29 +297,29 @@ NETSTAT_ENTRY(rx_compressed); NETSTAT_ENTRY(tx_compressed); static struct attribute *netstat_attrs[] = { - &dev_attr_rx_packets.attr, - &dev_attr_tx_packets.attr, - &dev_attr_rx_bytes.attr, - &dev_attr_tx_bytes.attr, - &dev_attr_rx_errors.attr, - &dev_attr_tx_errors.attr, - &dev_attr_rx_dropped.attr, - &dev_attr_tx_dropped.attr, - &dev_attr_multicast.attr, - &dev_attr_collisions.attr, - &dev_attr_rx_length_errors.attr, - &dev_attr_rx_over_errors.attr, - &dev_attr_rx_crc_errors.attr, - &dev_attr_rx_frame_errors.attr, - &dev_attr_rx_fifo_errors.attr, - &dev_attr_rx_missed_errors.attr, - &dev_attr_tx_aborted_errors.attr, - &dev_attr_tx_carrier_errors.attr, - &dev_attr_tx_fifo_errors.attr, - &dev_attr_tx_heartbeat_errors.attr, - &dev_attr_tx_window_errors.attr, - &dev_attr_rx_compressed.attr, - &dev_attr_tx_compressed.attr, + &class_device_attr_rx_packets.attr, + &class_device_attr_tx_packets.attr, + &class_device_attr_rx_bytes.attr, + &class_device_attr_tx_bytes.attr, + &class_device_attr_rx_errors.attr, + &class_device_attr_tx_errors.attr, + &class_device_attr_rx_dropped.attr, + &class_device_attr_tx_dropped.attr, + &class_device_attr_multicast.attr, + &class_device_attr_collisions.attr, + &class_device_attr_rx_length_errors.attr, + &class_device_attr_rx_over_errors.attr, + &class_device_attr_rx_crc_errors.attr, + &class_device_attr_rx_frame_errors.attr, + &class_device_attr_rx_fifo_errors.attr, + &class_device_attr_rx_missed_errors.attr, + &class_device_attr_tx_aborted_errors.attr, + &class_device_attr_tx_carrier_errors.attr, + &class_device_attr_tx_fifo_errors.attr, + &class_device_attr_tx_heartbeat_errors.attr, + &class_device_attr_tx_window_errors.attr, + &class_device_attr_rx_compressed.attr, + &class_device_attr_tx_compressed.attr, NULL }; @@ -342,11 +331,11 @@ static struct attribute_group netstat_group = { #ifdef WIRELESS_EXT /* helper function that does all the locking etc for wireless stats */ -static ssize_t wireless_show(struct device *d, char *buf, +static ssize_t wireless_show(struct class_device *cd, char *buf, ssize_t (*format)(const struct iw_statistics *, char *)) { - struct net_device *dev = to_net_dev(d); + struct net_device *dev = to_net_dev(cd); const struct iw_statistics *iw = NULL; ssize_t ret = -EINVAL; @@ -369,12 +358,11 @@ static ssize_t format_iw_##name(const struct iw_statistics *iw, char *buf) \ { \ return sprintf(buf, format_string, iw->field); \ } \ -static ssize_t show_iw_##name(struct device *d, \ - struct device_attribute *attr, char *buf) \ +static ssize_t show_iw_##name(struct class_device *cd, char *buf) \ { \ - return wireless_show(d, buf, format_iw_##name); \ + return wireless_show(cd, buf, format_iw_##name); \ } \ -static DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL) +static CLASS_DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL) WIRELESS_SHOW(status, status, fmt_hex); WIRELESS_SHOW(link, qual.qual, fmt_dec); @@ -388,16 +376,16 @@ WIRELESS_SHOW(retries, discard.retries, fmt_dec); WIRELESS_SHOW(beacon, miss.beacon, fmt_dec); static struct attribute *wireless_attrs[] = { - &dev_attr_status.attr, - &dev_attr_link.attr, - &dev_attr_level.attr, - &dev_attr_noise.attr, - &dev_attr_nwid.attr, - &dev_attr_crypt.attr, - &dev_attr_fragment.attr, - &dev_attr_retries.attr, - &dev_attr_misc.attr, - &dev_attr_beacon.attr, + &class_device_attr_status.attr, + &class_device_attr_link.attr, + &class_device_attr_level.attr, + &class_device_attr_noise.attr, + &class_device_attr_nwid.attr, + &class_device_attr_crypt.attr, + &class_device_attr_fragment.attr, + &class_device_attr_retries.attr, + &class_device_attr_misc.attr, + &class_device_attr_beacon.attr, NULL }; @@ -408,10 +396,10 @@ static struct attribute_group wireless_group = { #endif #ifdef CONFIG_HOTPLUG -static int netdev_uevent(struct device *d, char **envp, +static int netdev_uevent(struct class_device *cd, char **envp, int num_envp, char *buf, int size) { - struct net_device *dev = to_net_dev(d); + struct net_device *dev = to_net_dev(cd); int i = 0; int n; @@ -431,11 +419,12 @@ static int netdev_uevent(struct device *d, char **envp, /* * netdev_release -- destroy and free a dead device. - * Called when last reference to device kobject is gone. + * Called when last reference to class_device kobject is gone. */ -static void netdev_release(struct device *d) +static void netdev_release(struct class_device *cd) { - struct net_device *dev = to_net_dev(d); + struct net_device *dev + = container_of(cd, struct net_device, class_dev); BUG_ON(dev->reg_state != NETREG_RELEASED); @@ -444,31 +433,31 @@ static void netdev_release(struct device *d) static struct class net_class = { .name = "net", - .dev_release = netdev_release, - .dev_attrs = net_class_attributes, + .release = netdev_release, + .class_dev_attrs = net_class_attributes, #ifdef CONFIG_HOTPLUG - .dev_uevent = netdev_uevent, + .uevent = netdev_uevent, #endif }; void netdev_unregister_sysfs(struct net_device * net) { - device_del(&(net->dev)); + class_device_del(&(net->class_dev)); } /* Create sysfs entries for network device. */ int netdev_register_sysfs(struct net_device *net) { - struct device *dev = &(net->dev); + struct class_device *class_dev = &(net->class_dev); struct attribute_group **groups = net->sysfs_groups; - device_initialize(dev); - dev->class = &net_class; - dev->platform_data = net; - dev->groups = groups; + class_device_initialize(class_dev); + class_dev->class = &net_class; + class_dev->class_data = net; + class_dev->groups = groups; BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ); - strlcpy(dev->bus_id, net->name, BUS_ID_SIZE); + strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE); if (net->get_stats) *groups++ = &netstat_group; @@ -478,7 +467,7 @@ int netdev_register_sysfs(struct net_device *net) *groups++ = &wireless_group; #endif - return device_add(dev); + return class_device_add(class_dev); } int netdev_sysfs_init(void) diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index f3404ae9f190..de7801d589e7 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -268,7 +268,7 @@ struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp, struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int length, gfp_t gfp_mask) { - int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; + int node = dev->class_dev.dev ? dev_to_node(dev->class_dev.dev) : -1; struct sk_buff *skb; skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node); diff --git a/trunk/net/ieee80211/softmac/ieee80211softmac_wx.c b/trunk/net/ieee80211/softmac/ieee80211softmac_wx.c index fb58e03b3fbd..fa2f7da606a9 100644 --- a/trunk/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/trunk/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -265,12 +265,6 @@ ieee80211softmac_wx_get_rate(struct net_device *net_dev, int err = -EINVAL; spin_lock_irqsave(&mac->lock, flags); - - if (unlikely(!mac->running)) { - err = -ENODEV; - goto out_unlock; - } - switch (mac->txrates.default_rate) { case IEEE80211_CCK_RATE_1MB: data->bitrate.value = 1000000; diff --git a/trunk/scripts/Kbuild.include b/trunk/scripts/Kbuild.include index a1880e854dce..d65c40331e66 100644 --- a/trunk/scripts/Kbuild.include +++ b/trunk/scripts/Kbuild.include @@ -60,15 +60,17 @@ endef # Usage: option = $(call checker-shell,$(CC)...-o $$OUT,option-ok,otherwise) # Exit code chooses option. $$OUT is safe location for needless output. define checker-shell -$(shell set -e; \ - DIR=$(KBUILD_EXTMOD); \ - cd $${DIR:-$(objtree)}; \ - OUT=$$PWD/.$$$$.null; \ - if $(1) >/dev/null 2>&1; \ - then echo "$(2)"; \ - else echo "$(3)"; \ - fi; \ - rm -f $$OUT) + $(shell set -e; \ + DIR=$(KBUILD_EXTMOD); \ + cd $${DIR:-$(objtree)}; \ + OUT=$$PWD/.$$$$.null; \ + \ + ln -s /dev/null $$OUT; \ + if $(1) >/dev/null 2>&1; \ + then echo "$(2)"; \ + else echo "$(3)"; \ + fi; \ + rm -f $$OUT) endef # as-option