From 3dd9b844eec011d43283ecb2e451d6e21194a194 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 May 2005 12:53:49 -0700 Subject: [PATCH] --- yaml --- r: 1447 b: refs/heads/master c: 0afb51e72855971dba83b3c6b70c547c2d1161fd h: refs/heads/master i: 1445: fa50febdf46f7f68c210c0838ce0b02ac44899c3 1443: 5d7e737cab074a0a48db154da92f9c76a5056fbc 1439: d6069689137c1bc9ae6ca3dea05b0f64885ab373 v: v3 --- [refs] | 2 +- trunk/drivers/net/Kconfig | 1 - trunk/drivers/net/forcedeth.c | 103 +---- trunk/drivers/net/iseries_veth.c | 32 +- trunk/drivers/net/natsemi.c | 6 +- trunk/drivers/net/ns83820.c | 69 +-- trunk/drivers/net/sis900.c | 52 +-- trunk/drivers/net/tlan.c | 12 - trunk/drivers/net/wireless/airo.c | 150 ++----- trunk/drivers/net/wireless/atmel_cs.c | 1 - trunk/drivers/s390/net/Makefile | 3 +- trunk/drivers/s390/net/ctcdbug.h | 12 +- trunk/drivers/s390/net/ctcmain.c | 616 +++++++++++++++++--------- trunk/drivers/s390/net/ctcmain.h | 276 ------------ trunk/drivers/s390/net/ctctty.c | 5 +- trunk/drivers/s390/net/cu3088.c | 4 +- trunk/drivers/s390/net/cu3088.h | 3 - trunk/drivers/s390/net/iucv.c | 10 +- trunk/drivers/s390/net/lcs.c | 33 +- trunk/drivers/s390/net/qeth.h | 35 +- trunk/drivers/s390/net/qeth_eddp.c | 51 ++- trunk/drivers/s390/net/qeth_main.c | 316 +++++-------- trunk/drivers/s390/net/qeth_tso.c | 285 ++++++++++++ trunk/drivers/s390/net/qeth_tso.h | 166 ++----- trunk/net/sched/sch_netem.c | 53 ++- 25 files changed, 1049 insertions(+), 1247 deletions(-) delete mode 100644 trunk/drivers/s390/net/ctcmain.h create mode 100644 trunk/drivers/s390/net/qeth_tso.c diff --git a/[refs] b/[refs] index 9cf3788ad62c..ab38f7e69d35 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f49809fe9b39e22b0f6f75c86295ce216ce3e374 +refs/heads/master: 0afb51e72855971dba83b3c6b70c547c2d1161fd diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 7c5c1acd1474..3a0a55b62aaf 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -1555,7 +1555,6 @@ config SIS900 tristate "SiS 900/7016 PCI Fast Ethernet Adapter support" depends on NET_PCI && PCI select CRC32 - select MII ---help--- This is a driver for the Fast Ethernet PCI network cards based on the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c index 4ebcd052e150..cda48c5d72a9 100644 --- a/trunk/drivers/net/forcedeth.c +++ b/trunk/drivers/net/forcedeth.c @@ -81,7 +81,6 @@ * cause DMA to kfree'd memory. * 0.31: 14 Nov 2004: ethtool support for getting/setting link * capabilities. - * 0.32: 16 Apr 2005: RX_ERROR4 handling added. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -93,7 +92,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.32" +#define FORCEDETH_VERSION "0.31" #define DRV_NAME "forcedeth" #include @@ -110,7 +109,6 @@ #include #include #include -#include #include #include @@ -1015,59 +1013,6 @@ static void nv_tx_timeout(struct net_device *dev) spin_unlock_irq(&np->lock); } -/* - * Called when the nic notices a mismatch between the actual data len on the - * wire and the len indicated in the 802 header - */ -static int nv_getlen(struct net_device *dev, void *packet, int datalen) -{ - int hdrlen; /* length of the 802 header */ - int protolen; /* length as stored in the proto field */ - - /* 1) calculate len according to header */ - if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == __constant_htons(ETH_P_8021Q)) { - protolen = ntohs( ((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto ); - hdrlen = VLAN_HLEN; - } else { - protolen = ntohs( ((struct ethhdr *)packet)->h_proto); - hdrlen = ETH_HLEN; - } - dprintk(KERN_DEBUG "%s: nv_getlen: datalen %d, protolen %d, hdrlen %d\n", - dev->name, datalen, protolen, hdrlen); - if (protolen > ETH_DATA_LEN) - return datalen; /* Value in proto field not a len, no checks possible */ - - protolen += hdrlen; - /* consistency checks: */ - if (datalen > ETH_ZLEN) { - if (datalen >= protolen) { - /* more data on wire than in 802 header, trim of - * additional data. - */ - dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n", - dev->name, protolen); - return protolen; - } else { - /* less data on wire than mentioned in header. - * Discard the packet. - */ - 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 void nv_rx_process(struct net_device *dev) { struct fe_priv *np = get_nvpriv(dev); @@ -1119,7 +1064,7 @@ static void nv_rx_process(struct net_device *dev) np->stats.rx_errors++; goto next_pkt; } - if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) { + if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3|NV_RX_ERROR4)) { np->stats.rx_errors++; goto next_pkt; } @@ -1133,24 +1078,22 @@ static void nv_rx_process(struct net_device *dev) 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) { + if (Flags & NV_RX_ERROR) { + /* framing errors are soft errors, the rest is fatal. */ + if (Flags & NV_RX_FRAMINGERR) { + if (Flags & NV_RX_SUBSTRACT1) { + len--; + } + } else { 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_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) { + if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3|NV_RX2_ERROR4)) { np->stats.rx_errors++; goto next_pkt; } @@ -1164,19 +1107,17 @@ static void nv_rx_process(struct net_device *dev) np->stats.rx_errors++; goto next_pkt; } - if (Flags & NV_RX2_ERROR4) { - len = nv_getlen(dev, np->rx_skbuff[i]->data, len); - if (len < 0) { + if (Flags & NV_RX2_ERROR) { + /* framing errors are soft errors, the rest is fatal. */ + if (Flags & NV_RX2_FRAMINGERR) { + if (Flags & NV_RX2_SUBSTRACT1) { + len--; + } + } else { np->stats.rx_errors++; goto next_pkt; } } - /* framing errors are soft errors */ - if (Flags & NV_RX2_FRAMINGERR) { - if (Flags & NV_RX2_SUBSTRACT1) { - len--; - } - } Flags &= NV_RX2_CHECKSUMMASK; if (Flags == NV_RX2_CHECKSUMOK1 || Flags == NV_RX2_CHECKSUMOK2 || @@ -1539,13 +1480,6 @@ static void nv_do_nic_poll(unsigned long data) enable_irq(dev->irq); } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void nv_poll_controller(struct net_device *dev) -{ - nv_do_nic_poll((unsigned long) dev); -} -#endif - static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct fe_priv *np = get_nvpriv(dev); @@ -2028,9 +1962,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->get_stats = nv_get_stats; dev->change_mtu = nv_change_mtu; dev->set_multicast_list = nv_set_multicast; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = nv_poll_controller; -#endif SET_ETHTOOL_OPS(dev, &ops); dev->tx_timeout = nv_tx_timeout; dev->watchdog_timeo = NV_WATCHDOG_TIMEO; diff --git a/trunk/drivers/net/iseries_veth.c b/trunk/drivers/net/iseries_veth.c index 13ed8dc1e91d..855f8b2cf13b 100644 --- a/trunk/drivers/net/iseries_veth.c +++ b/trunk/drivers/net/iseries_veth.c @@ -924,7 +924,7 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp, spin_lock_irqsave(&cnx->lock, flags); - if (! (cnx->state & VETH_STATE_READY)) + if (! cnx->state & VETH_STATE_READY) goto drop; if ((skb->len - 14) > VETH_MAX_MTU) @@ -1023,8 +1023,6 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev) lpmask = veth_transmit_to_many(skb, lpmask, dev); - dev->trans_start = jiffies; - if (! lpmask) { dev_kfree_skb(skb); } else { @@ -1264,18 +1262,13 @@ static void veth_receive(struct veth_lpar_connection *cnx, vlan = skb->data[9]; dev = veth_dev[vlan]; - if (! dev) { - /* - * Some earlier versions of the driver sent - * broadcasts down all connections, even to lpars - * that weren't on the relevant vlan. So ignore - * packets belonging to a vlan we're not on. - * We can also be here if we receive packets while - * the driver is going down, because then dev is NULL. - */ - dev_kfree_skb_irq(skb); + if (! dev) + /* Some earlier versions of the driver sent + broadcasts down all connections, even to + lpars that weren't on the relevant vlan. + So ignore packets belonging to a vlan we're + not on. */ continue; - } port = (struct veth_port *)dev->priv; dest = *((u64 *) skb->data) & 0xFFFFFFFFFFFF0000; @@ -1388,25 +1381,18 @@ void __exit veth_module_cleanup(void) { int i; - /* Stop the queues first to stop any new packets being sent. */ - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) - if (veth_dev[i]) - netif_stop_queue(veth_dev[i]); + vio_unregister_driver(&veth_driver); - /* Stop the connections before we unregister the driver. This - * ensures there's no skbs lying around holding the device open. */ for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) veth_stop_connection(i); HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan); /* Hypervisor callbacks may have scheduled more work while we - * were stoping connections. Now that we've disconnected from + * were destroying connections. Now that we've disconnected from * the hypervisor make sure everything's finished. */ flush_scheduled_work(); - vio_unregister_driver(&veth_driver); - for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) veth_destroy_connection(i); diff --git a/trunk/drivers/net/natsemi.c b/trunk/drivers/net/natsemi.c index babb59e146ea..223bdadd4c0d 100644 --- a/trunk/drivers/net/natsemi.c +++ b/trunk/drivers/net/natsemi.c @@ -2433,9 +2433,9 @@ static void __set_rx_mode(struct net_device *dev) rx_mode = RxFilterEnable | AcceptBroadcast | AcceptMulticast | AcceptMyPhys; for (i = 0; i < 64; i += 2) { - writel(HASH_TABLE + i, ioaddr + RxFilterAddr); - writel((mc_filter[i + 1] << 8) + mc_filter[i], - ioaddr + RxFilterData); + writew(HASH_TABLE + i, ioaddr + RxFilterAddr); + writew((mc_filter[i+1]<<8) + mc_filter[i], + ioaddr + RxFilterData); } } writel(rx_mode, ioaddr + RxFilterAddr); diff --git a/trunk/drivers/net/ns83820.c b/trunk/drivers/net/ns83820.c index c336b46bd332..2fcc181a8624 100644 --- a/trunk/drivers/net/ns83820.c +++ b/trunk/drivers/net/ns83820.c @@ -1,4 +1,4 @@ -#define VERSION "0.22" +#define _VERSION "0.20" /* ns83820.c by Benjamin LaHaise with contributions. * * Questions/comments/discussion to linux-ns83820@kvack.org. @@ -63,11 +63,9 @@ * - fix missed txok introduced during performance * tuning * 0.20 - fix stupid RFEN thinko. i am such a smurf. + * * 20040828 0.21 - add hardware vlan accleration * by Neil Horman - * 20050406 0.22 - improved DAC ifdefs from Andi Kleen - * - removal of dead code from Adrian Bunk - * - fix half duplex collision behaviour * Driver Overview * =============== * @@ -131,6 +129,18 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #undef Dprintk #define Dprintk dprintk +#if defined(CONFIG_HIGHMEM64G) || defined(__ia64__) +#define USE_64BIT_ADDR "+" +#endif + +#if defined(USE_64BIT_ADDR) +#define VERSION _VERSION USE_64BIT_ADDR +#define TRY_DAC 1 +#else +#define VERSION _VERSION +#define TRY_DAC 0 +#endif + /* tunables */ #define RX_BUF_SIZE 1500 /* 8192 */ #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) @@ -376,16 +386,22 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */ #define LINK_DOWN 0x02 #define LINK_UP 0x04 -#define HW_ADDR_LEN sizeof(dma_addr_t) +#ifdef USE_64BIT_ADDR +#define HW_ADDR_LEN 8 #define desc_addr_set(desc, addr) \ do { \ - ((desc)[0] = cpu_to_le32(addr)); \ - if (HW_ADDR_LEN == 8) \ - (desc)[1] = cpu_to_le32(((u64)addr) >> 32); \ + u64 __addr = (addr); \ + (desc)[0] = cpu_to_le32(__addr); \ + (desc)[1] = cpu_to_le32(__addr >> 32); \ } while(0) #define desc_addr_get(desc) \ - (le32_to_cpu((desc)[0]) | \ - (HW_ADDR_LEN == 8 ? ((dma_addr_t)le32_to_cpu((desc)[1]))<<32 : 0)) + (((u64)le32_to_cpu((desc)[1]) << 32) \ + | le32_to_cpu((desc)[0])) +#else +#define HW_ADDR_LEN 4 +#define desc_addr_set(desc, addr) ((desc)[0] = cpu_to_le32(addr)) +#define desc_addr_get(desc) (le32_to_cpu((desc)[0])) +#endif #define DESC_LINK 0 #define DESC_BUFPTR (DESC_LINK + HW_ADDR_LEN/4) @@ -711,23 +727,11 @@ static void fastcall phy_intr(struct net_device *ndev) speed = ((cfg / CFG_SPDSTS0) & 3); fullduplex = (cfg & CFG_DUPSTS); - if (fullduplex) { + if (fullduplex) new_cfg |= CFG_SB; - writel(readl(dev->base + TXCFG) - | TXCFG_CSI | TXCFG_HBI, - dev->base + TXCFG); - writel(readl(dev->base + RXCFG) | RXCFG_RX_FD, - dev->base + RXCFG); - } else { - writel(readl(dev->base + TXCFG) - & ~(TXCFG_CSI | TXCFG_HBI), - dev->base + TXCFG); - writel(readl(dev->base + RXCFG) & ~(RXCFG_RX_FD), - dev->base + RXCFG); - } if ((cfg & CFG_LNKSTS) && - ((new_cfg ^ dev->CFG_cache) != 0)) { + ((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) { writel(new_cfg, dev->base + CFG); dev->CFG_cache = new_cfg; } @@ -1185,6 +1189,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) for (;;) { volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE); + u32 residue = 0; dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len, (unsigned long long)buf); @@ -1194,11 +1199,17 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) desc_addr_set(desc + DESC_BUFPTR, buf); desc[DESC_EXTSTS] = cpu_to_le32(extsts); - cmdsts = ((nr_frags) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0); + cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0); cmdsts |= (desc == first_desc) ? 0 : CMDSTS_OWN; cmdsts |= len; desc[DESC_CMDSTS] = cpu_to_le32(cmdsts); + if (residue) { + buf += len; + len = residue; + continue; + } + if (!nr_frags) break; @@ -1830,8 +1841,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ int using_dac = 0; /* See if we can set the dma mask early on; failure is fatal. */ - if (sizeof(dma_addr_t) == 8 && - !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) { + if (TRY_DAC && !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) { using_dac = 1; } else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) { using_dac = 0; @@ -1962,8 +1972,9 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ /* When compiled with 64 bit addressing, we must always enable * the 64 bit descriptor format. */ - if (sizeof(dma_addr_t) == 8) - dev->CFG_cache |= CFG_M64ADDR; +#ifdef USE_64BIT_ADDR + dev->CFG_cache |= CFG_M64ADDR; +#endif if (using_dac) dev->CFG_cache |= CFG_T64ADDR; diff --git a/trunk/drivers/net/sis900.c b/trunk/drivers/net/sis900.c index 3107aed0fb51..3e9d9aab0588 100644 --- a/trunk/drivers/net/sis900.c +++ b/trunk/drivers/net/sis900.c @@ -162,7 +162,6 @@ struct sis900_private { struct mii_phy * mii; struct mii_phy * first_mii; /* record the first mii structure */ unsigned int cur_phy; - struct mii_if_info mii_info; struct timer_list timer; /* Link status detection timer. */ u8 autong_complete; /* 1: auto-negotiate complete */ @@ -204,7 +203,7 @@ static int sis900_open(struct net_device *net_dev); static int sis900_mii_probe (struct net_device * net_dev); static void sis900_init_rxfilter (struct net_device * net_dev); static u16 read_eeprom(long ioaddr, int location); -static int mdio_read(struct net_device *net_dev, int phy_id, int location); +static u16 mdio_read(struct net_device *net_dev, int phy_id, int location); static void mdio_write(struct net_device *net_dev, int phy_id, int location, int val); static void sis900_timer(unsigned long data); static void sis900_check_mode (struct net_device *net_dev, struct mii_phy *mii_phy); @@ -479,13 +478,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev, sis_priv->msg_enable = sis900_debug; else sis_priv->msg_enable = SIS900_DEF_MSG; - - sis_priv->mii_info.dev = net_dev; - sis_priv->mii_info.mdio_read = mdio_read; - sis_priv->mii_info.mdio_write = mdio_write; - sis_priv->mii_info.phy_id_mask = 0x1f; - sis_priv->mii_info.reg_num_mask = 0x1f; - + /* Get Mac address according to the chip revision */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &(sis_priv->chipset_rev)); if(netif_msg_probe(sis_priv)) @@ -732,8 +725,6 @@ static u16 sis900_default_phy(struct net_device * net_dev) pci_name(sis_priv->pci_dev), sis_priv->cur_phy); } - sis_priv->mii_info.phy_id = sis_priv->cur_phy; - status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL); status &= (~MII_CNTL_ISOLATE); @@ -861,7 +852,7 @@ static void mdio_reset(long mdio_addr) * Please see SiS7014 or ICS spec */ -static int mdio_read(struct net_device *net_dev, int phy_id, int location) +static u16 mdio_read(struct net_device *net_dev, int phy_id, int location) { long mdio_addr = net_dev->base_addr + mear; int mii_cmd = MIIread|(phy_id<msg_enable = value; } -static u32 sis900_get_link(struct net_device *net_dev) -{ - struct sis900_private *sis_priv = net_dev->priv; - return mii_link_ok(&sis_priv->mii_info); -} - -static int sis900_get_settings(struct net_device *net_dev, - struct ethtool_cmd *cmd) -{ - struct sis900_private *sis_priv = net_dev->priv; - spin_lock_irq(&sis_priv->lock); - mii_ethtool_gset(&sis_priv->mii_info, cmd); - spin_unlock_irq(&sis_priv->lock); - return 0; -} - -static int sis900_set_settings(struct net_device *net_dev, - struct ethtool_cmd *cmd) -{ - struct sis900_private *sis_priv = net_dev->priv; - int rt; - spin_lock_irq(&sis_priv->lock); - rt = mii_ethtool_sset(&sis_priv->mii_info, cmd); - spin_unlock_irq(&sis_priv->lock); - return rt; -} - -static int sis900_nway_reset(struct net_device *net_dev) -{ - struct sis900_private *sis_priv = net_dev->priv; - return mii_nway_restart(&sis_priv->mii_info); -} - static struct ethtool_ops sis900_ethtool_ops = { .get_drvinfo = sis900_get_drvinfo, .get_msglevel = sis900_get_msglevel, .set_msglevel = sis900_set_msglevel, - .get_link = sis900_get_link, - .get_settings = sis900_get_settings, - .set_settings = sis900_set_settings, - .nway_reset = sis900_nway_reset, }; /** diff --git a/trunk/drivers/net/tlan.c b/trunk/drivers/net/tlan.c index 9680a308c62b..a7ffa64502dd 100644 --- a/trunk/drivers/net/tlan.c +++ b/trunk/drivers/net/tlan.c @@ -193,12 +193,6 @@ static int aui[MAX_TLAN_BOARDS]; static int duplex[MAX_TLAN_BOARDS]; static int speed[MAX_TLAN_BOARDS]; static int boards_found; -module_param_array(aui, int, NULL, 0); -module_param_array(duplex, int, NULL, 0); -module_param_array(speed, int, NULL, 0); -MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)"); -MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)"); -MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)"); MODULE_AUTHOR("Maintainer: Samuel Chessman "); MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters"); @@ -210,13 +204,8 @@ MODULE_LICENSE("GPL"); /* Turn on debugging. See Documentation/networking/tlan.txt for details */ static int debug; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "ThunderLAN debug mask"); static int bbuf; -module_param(bbuf, int, 0); -MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)"); - static u8 *TLanPadBuffer; static dma_addr_t TLanPadBufferDMA; static char TLanSignature[] = "TLAN"; @@ -2392,7 +2381,6 @@ TLan_FinishReset( struct net_device *dev ) TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET ); return; } - TLan_SetMulticastList(dev); } /* TLan_FinishReset */ diff --git a/trunk/drivers/net/wireless/airo.c b/trunk/drivers/net/wireless/airo.c index fb10a2db63ad..463c789cdc77 100644 --- a/trunk/drivers/net/wireless/airo.c +++ b/trunk/drivers/net/wireless/airo.c @@ -754,7 +754,7 @@ typedef struct { u8 zero; u8 ssidLen; u8 ssid[32]; - u16 dBm; + u16 rssi; #define CAP_ESS (1<<0) #define CAP_IBSS (1<<1) #define CAP_PRIVACY (1<<4) @@ -1125,9 +1125,6 @@ static int micsetup(struct airo_info *ai); static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len); static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen); -static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi); -static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm); - #include #endif @@ -1716,7 +1713,6 @@ static int readBSSListRid(struct airo_info *ai, int first, list->fh.dwell = le16_to_cpu(list->fh.dwell); list->dsChannel = le16_to_cpu(list->dsChannel); list->atimWindow = le16_to_cpu(list->atimWindow); - list->dBm = le16_to_cpu(list->dBm); return rc; } @@ -3249,10 +3245,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm; else wstats.level = (hdr.rssi[1] + 321) / 2; - wstats.noise = apriv->wstats.qual.noise; - wstats.updated = IW_QUAL_LEVEL_UPDATED - | IW_QUAL_QUAL_UPDATED - | IW_QUAL_NOISE_UPDATED; + wstats.updated = 3; /* Update spy records */ wireless_spy_update(dev, sa, &wstats); } @@ -3595,10 +3588,7 @@ void mpi_receive_802_11 (struct airo_info *ai) wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm; else wstats.level = (hdr.rssi[1] + 321) / 2; - wstats.noise = ai->wstats.qual.noise; - wstats.updated = IW_QUAL_QUAL_UPDATED - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_NOISE_UPDATED; + wstats.updated = 3; /* Update spy records */ wireless_spy_update(ai->dev, sa, &wstats); } @@ -3689,7 +3679,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock); if ( status == SUCCESS ) { if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL) - memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */ + memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); } else { if (ai->rssi) { @@ -5358,7 +5348,7 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) { (int)BSSList_rid.bssid[5], (int)BSSList_rid.ssidLen, BSSList_rid.ssid, - (int)BSSList_rid.dBm); + (int)BSSList_rid.rssi); ptr += sprintf(ptr, " channel = %d %s %s %s %s\n", (int)BSSList_rid.dsChannel, BSSList_rid.cap & CAP_ESS ? "ESS" : "", @@ -5603,29 +5593,6 @@ static void __exit airo_cleanup_module( void ) * would not work at all... - Jean II */ -static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi) -{ - if( !rssi_rid ) - return 0; - - return (0x100 - rssi_rid[rssi].rssidBm); -} - -static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm) -{ - int i; - - if( !rssi_rid ) - return 0; - - for( i = 0; i < 256; i++ ) - if (rssi_rid[i].rssidBm == dbm) - return rssi_rid[i].rssipct; - - return 0; -} - - static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) { int quality = 0; @@ -6476,29 +6443,11 @@ static int airo_get_range(struct net_device *dev, } range->num_frequency = k; - range->sensitivity = 65535; - /* Hum... Should put the right values there */ - if (local->rssi) - range->max_qual.qual = 100; /* % */ - else - range->max_qual.qual = airo_get_max_quality(&cap_rid); - range->max_qual.level = 0; /* 0 means we use dBm */ + range->max_qual.qual = airo_get_max_quality(&cap_rid); + range->max_qual.level = 0x100 - 120; /* -120 dBm */ range->max_qual.noise = 0; - range->max_qual.updated = 0; - - /* Experimental measurements - boundary 11/5.5 Mb/s */ - /* Note : with or without the (local->rssi), results - * are somewhat different. - Jean II */ - if (local->rssi) { - range->avg_qual.qual = 50; /* % */ - range->avg_qual.level = 186; /* -70 dBm */ - } else { - range->avg_qual.qual = airo_get_avg_quality(&cap_rid); - range->avg_qual.level = 176; /* -80 dBm */ - } - range->avg_qual.noise = 0; - range->avg_qual.updated = 0; + range->sensitivity = 65535; for(i = 0 ; i < 8 ; i++) { range->bitrate[i] = cap_rid.supportedRates[i] * 500000; @@ -6559,6 +6508,15 @@ static int airo_get_range(struct net_device *dev, range->max_retry = 65535; range->min_r_time = 1024; range->max_r_time = 65535 * 1024; + /* Experimental measurements - boundary 11/5.5 Mb/s */ + /* Note : with or without the (local->rssi), results + * are somewhat different. - Jean II */ + range->avg_qual.qual = airo_get_avg_quality(&cap_rid); + if (local->rssi) + range->avg_qual.level = 186; /* -70 dBm */ + else + range->avg_qual.level = 176; /* -80 dBm */ + range->avg_qual.noise = 0; /* Event capability (kernel + driver) */ range->event_capa[0] = (IW_EVENT_CAPA_K_0 | @@ -6718,18 +6676,12 @@ static int airo_get_aplist(struct net_device *dev, loseSync = 0; memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN); address[i].sa_family = ARPHRD_ETHER; - if (local->rssi) { - qual[i].level = 0x100 - BSSList.dBm; - qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm ); - qual[i].updated = IW_QUAL_QUAL_UPDATED; - } else { - qual[i].level = (BSSList.dBm + 321) / 2; - qual[i].qual = 0; - qual[i].updated = IW_QUAL_QUAL_INVALID; - } - qual[i].noise = local->wstats.qual.noise; - qual[i].updated = IW_QUAL_LEVEL_UPDATED - | IW_QUAL_NOISE_UPDATED; + if (local->rssi) + qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm; + else + qual[i].level = (BSSList.rssi + 321) / 2; + qual[i].qual = qual[i].noise = 0; + qual[i].updated = 2; if (BSSList.index == 0xffff) break; } @@ -6808,7 +6760,7 @@ static int airo_set_scan(struct net_device *dev, static inline char *airo_translate_scan(struct net_device *dev, char *current_ev, char *end_buf, - BSSListRid *bss) + BSSListRid *list) { struct airo_info *ai = dev->priv; struct iw_event iwe; /* Temporary buffer */ @@ -6819,22 +6771,22 @@ static inline char *airo_translate_scan(struct net_device *dev, /* First entry *MUST* be the AP MAC address */ iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); + memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN); current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); /* Other entries will be displayed in the order we give them */ /* Add the ESSID */ - iwe.u.data.length = bss->ssidLen; + iwe.u.data.length = list->ssidLen; if(iwe.u.data.length > 32) iwe.u.data.length = 32; iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid); /* Add mode */ iwe.cmd = SIOCGIWMODE; - capabilities = le16_to_cpu(bss->cap); + capabilities = le16_to_cpu(list->cap); if(capabilities & (CAP_ESS | CAP_IBSS)) { if(capabilities & CAP_ESS) iwe.u.mode = IW_MODE_MASTER; @@ -6845,25 +6797,19 @@ static inline char *airo_translate_scan(struct net_device *dev, /* Add frequency */ iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = le16_to_cpu(bss->dsChannel); + iwe.u.freq.m = le16_to_cpu(list->dsChannel); iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000; iwe.u.freq.e = 1; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); /* Add quality statistics */ iwe.cmd = IWEVQUAL; - if (ai->rssi) { - iwe.u.qual.level = 0x100 - bss->dBm; - iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm ); - iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED; - } else { - iwe.u.qual.level = (bss->dBm + 321) / 2; - iwe.u.qual.qual = 0; - iwe.u.qual.updated = IW_QUAL_QUAL_INVALID; - } - iwe.u.qual.noise = ai->wstats.qual.noise; - iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED - | IW_QUAL_NOISE_UPDATED; + if (ai->rssi) + iwe.u.qual.level = 0x100 - ai->rssi[list->rssi].rssidBm; + else + iwe.u.qual.level = (list->rssi + 321) / 2; + iwe.u.qual.noise = 0; + iwe.u.qual.qual = 0; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); /* Add encryption capability */ @@ -6873,7 +6819,7 @@ static inline char *airo_translate_scan(struct net_device *dev, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid); /* Rate : stuffing multiple values in a single event require a bit * more of magic - Jean II */ @@ -6885,10 +6831,10 @@ static inline char *airo_translate_scan(struct net_device *dev, /* Max 8 values */ for(i = 0 ; i < 8 ; i++) { /* NULL terminated */ - if(bss->rates[i] == 0) + if(list->rates[i] == 0) break; /* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000); + iwe.u.bitrate.value = ((list->rates[i] & 0x7f) * 500000); /* Add new value to event */ current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } @@ -7207,22 +7153,18 @@ static void airo_read_wireless_stats(struct airo_info *local) /* The status */ local->wstats.status = status_rid.mode; - /* Signal quality and co */ - if (local->rssi) { - local->wstats.qual.level = airo_rssi_to_dbm( local->rssi, status_rid.sigQuality ); - /* normalizedSignalStrength appears to be a percentage */ - local->wstats.qual.qual = status_rid.normalizedSignalStrength; - } else { + /* Signal quality and co. But where is the noise level ??? */ + local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); + if (local->rssi) + local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm; + else local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2; - local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); - } - local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED; if (status_rid.len >= 124) { - local->wstats.qual.noise = 0x100 - status_rid.noisedBm; - local->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED; + local->wstats.qual.noise = 256 - status_rid.noisedBm; + local->wstats.qual.updated = 7; } else { local->wstats.qual.noise = 0; - local->wstats.qual.updated |= IW_QUAL_NOISE_INVALID; + local->wstats.qual.updated = 3; } /* Packets discarded in the wireless adapter due to wireless diff --git a/trunk/drivers/net/wireless/atmel_cs.c b/trunk/drivers/net/wireless/atmel_cs.c index a4ed28d9c783..a91b507e0a7a 100644 --- a/trunk/drivers/net/wireless/atmel_cs.c +++ b/trunk/drivers/net/wireless/atmel_cs.c @@ -321,7 +321,6 @@ static struct { { 0x01bf, 0x3302, NULL, ATMEL_FW_TYPE_502E, "Belkin F5D6020-V2" }, { 0, 0, "BT/Voyager 1020 Laptop Adapter", ATMEL_FW_TYPE_502, "BT Voyager 1020" }, { 0, 0, "IEEE 802.11b/Wireless LAN PC Card", ATMEL_FW_TYPE_502, "Siemens Gigaset PC Card II" }, - { 0, 0, "IEEE 802.11b/Wireless LAN Card S", ATMEL_FW_TYPE_504_2958, "Siemens Gigaset PC Card II" }, { 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", ATMEL_FW_TYPE_502E, "CNet CNWLC-811ARL" }, { 0, 0, "Wireless/PC_CARD", ATMEL_FW_TYPE_502D, "Planet WL-3552" }, { 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", ATMEL_FW_TYPE_502, "OEM 11Mbps WLAN PCMCIA Card" }, diff --git a/trunk/drivers/s390/net/Makefile b/trunk/drivers/s390/net/Makefile index 90d4d0ef3dd4..7cabb80a2e41 100644 --- a/trunk/drivers/s390/net/Makefile +++ b/trunk/drivers/s390/net/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o obj-$(CONFIG_SMSGIUCV) += smsgiucv.o obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o obj-$(CONFIG_LCS) += lcs.o cu3088.o -obj-$(CONFIG_CLAW) += claw.o cu3088.o -qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o +qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth_tso.o qeth-$(CONFIG_PROC_FS) += qeth_proc.o obj-$(CONFIG_QETH) += qeth.o diff --git a/trunk/drivers/s390/net/ctcdbug.h b/trunk/drivers/s390/net/ctcdbug.h index 7fe2ebd1792d..ef8883951720 100644 --- a/trunk/drivers/s390/net/ctcdbug.h +++ b/trunk/drivers/s390/net/ctcdbug.h @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.5 $) + * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.4 $) * * CTC / ESCON network driver - s390 dbf exploit. * @@ -9,7 +9,7 @@ * Author(s): Original Code written by * Peter Tiedemann (ptiedem@de.ibm.com) * - * $Revision: 1.5 $ $Date: 2005/02/27 19:46:44 $ + * $Revision: 1.4 $ $Date: 2004/10/15 09:26:58 $ * * 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 @@ -25,11 +25,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _CTCDBUG_H_ -#define _CTCDBUG_H_ + #include -#include "ctcmain.h" /** * Debug Facility stuff */ @@ -43,7 +41,7 @@ #define CTC_DBF_DATA_LEN 128 #define CTC_DBF_DATA_INDEX 3 #define CTC_DBF_DATA_NR_AREAS 1 -#define CTC_DBF_DATA_LEVEL 3 +#define CTC_DBF_DATA_LEVEL 2 #define CTC_DBF_TRACE_NAME "ctc_trace" #define CTC_DBF_TRACE_LEN 16 @@ -123,5 +121,3 @@ hex_dump(unsigned char *buf, size_t len) printk("\n"); } - -#endif diff --git a/trunk/drivers/s390/net/ctcmain.c b/trunk/drivers/s390/net/ctcmain.c index ff3e95e07e89..7266bf5ea659 100644 --- a/trunk/drivers/s390/net/ctcmain.c +++ b/trunk/drivers/s390/net/ctcmain.c @@ -1,5 +1,5 @@ /* - * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $ + * $Id: ctcmain.c,v 1.72 2005/03/17 10:51:52 ptiedem Exp $ * * CTC / ESCON network driver * @@ -37,11 +37,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $ + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.72 $ * */ #undef DEBUG + #include #include #include @@ -73,13 +74,288 @@ #include "ctctty.h" #include "fsm.h" #include "cu3088.h" - #include "ctcdbug.h" -#include "ctcmain.h" MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)"); MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver"); MODULE_LICENSE("GPL"); + +/** + * CCW commands, used in this driver. + */ +#define CCW_CMD_WRITE 0x01 +#define CCW_CMD_READ 0x02 +#define CCW_CMD_SET_EXTENDED 0xc3 +#define CCW_CMD_PREPARE 0xe3 + +#define CTC_PROTO_S390 0 +#define CTC_PROTO_LINUX 1 +#define CTC_PROTO_LINUX_TTY 2 +#define CTC_PROTO_OS390 3 +#define CTC_PROTO_MAX 3 + +#define CTC_BUFSIZE_LIMIT 65535 +#define CTC_BUFSIZE_DEFAULT 32768 + +#define CTC_TIMEOUT_5SEC 5000 + +#define CTC_INITIAL_BLOCKLEN 2 + +#define READ 0 +#define WRITE 1 + +#define CTC_ID_SIZE BUS_ID_SIZE+3 + + +struct ctc_profile { + unsigned long maxmulti; + unsigned long maxcqueue; + unsigned long doios_single; + unsigned long doios_multi; + unsigned long txlen; + unsigned long tx_time; + struct timespec send_stamp; +}; + +/** + * Definition of one channel + */ +struct channel { + + /** + * Pointer to next channel in list. + */ + struct channel *next; + char id[CTC_ID_SIZE]; + struct ccw_device *cdev; + + /** + * Type of this channel. + * CTC/A or Escon for valid channels. + */ + enum channel_types type; + + /** + * Misc. flags. See CHANNEL_FLAGS_... below + */ + __u32 flags; + + /** + * The protocol of this channel + */ + __u16 protocol; + + /** + * I/O and irq related stuff + */ + struct ccw1 *ccw; + struct irb *irb; + + /** + * RX/TX buffer size + */ + int max_bufsize; + + /** + * Transmit/Receive buffer. + */ + struct sk_buff *trans_skb; + + /** + * Universal I/O queue. + */ + struct sk_buff_head io_queue; + + /** + * TX queue for collecting skb's during busy. + */ + struct sk_buff_head collect_queue; + + /** + * Amount of data in collect_queue. + */ + int collect_len; + + /** + * spinlock for collect_queue and collect_len + */ + spinlock_t collect_lock; + + /** + * Timer for detecting unresposive + * I/O operations. + */ + fsm_timer timer; + + /** + * Retry counter for misc. operations. + */ + int retry; + + /** + * The finite state machine of this channel + */ + fsm_instance *fsm; + + /** + * The corresponding net_device this channel + * belongs to. + */ + struct net_device *netdev; + + struct ctc_profile prof; + + unsigned char *trans_skb_data; + + __u16 logflags; +}; + +#define CHANNEL_FLAGS_READ 0 +#define CHANNEL_FLAGS_WRITE 1 +#define CHANNEL_FLAGS_INUSE 2 +#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4 +#define CHANNEL_FLAGS_FAILED 8 +#define CHANNEL_FLAGS_WAITIRQ 16 +#define CHANNEL_FLAGS_RWMASK 1 +#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK) + +#define LOG_FLAG_ILLEGALPKT 1 +#define LOG_FLAG_ILLEGALSIZE 2 +#define LOG_FLAG_OVERRUN 4 +#define LOG_FLAG_NOMEM 8 + +#define CTC_LOGLEVEL_INFO 1 +#define CTC_LOGLEVEL_NOTICE 2 +#define CTC_LOGLEVEL_WARN 4 +#define CTC_LOGLEVEL_EMERG 8 +#define CTC_LOGLEVEL_ERR 16 +#define CTC_LOGLEVEL_DEBUG 32 +#define CTC_LOGLEVEL_CRIT 64 + +#define CTC_LOGLEVEL_DEFAULT \ +(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT) + +#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1) + +static int loglevel = CTC_LOGLEVEL_DEFAULT; + +#define ctc_pr_debug(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0) + +#define ctc_pr_info(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0) + +#define ctc_pr_notice(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0) + +#define ctc_pr_warn(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0) + +#define ctc_pr_emerg(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0) + +#define ctc_pr_err(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0) + +#define ctc_pr_crit(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0) + +/** + * Linked list of all detected channels. + */ +static struct channel *channels = NULL; + +struct ctc_priv { + struct net_device_stats stats; + unsigned long tbusy; + /** + * The finite state machine of this interface. + */ + fsm_instance *fsm; + /** + * The protocol of this device + */ + __u16 protocol; + /** + * Timer for restarting after I/O Errors + */ + fsm_timer restart_timer; + + int buffer_size; + + struct channel *channel[2]; +}; + +/** + * Definition of our link level header. + */ +struct ll_header { + __u16 length; + __u16 type; + __u16 unused; +}; +#define LL_HEADER_LENGTH (sizeof(struct ll_header)) + +/** + * Compatibility macros for busy handling + * of network devices. + */ +static __inline__ void +ctc_clear_busy(struct net_device * dev) +{ + clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy)); + if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) + netif_wake_queue(dev); +} + +static __inline__ int +ctc_test_and_set_busy(struct net_device * dev) +{ + if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) + netif_stop_queue(dev); + return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy); +} + +/** + * Print Banner. + */ +static void +print_banner(void) +{ + static int printed = 0; + char vbuf[] = "$Revision: 1.72 $"; + char *version = vbuf; + + if (printed) + return; + if ((version = strchr(version, ':'))) { + char *p = strchr(version + 1, '$'); + if (p) + *p = '\0'; + } else + version = " ??? "; + printk(KERN_INFO "CTC driver Version%s" +#ifdef DEBUG + " (DEBUG-VERSION, " __DATE__ __TIME__ ")" +#endif + " initialized\n", version); + printed = 1; +} + +/** + * Return type of a detected device. + */ +static enum channel_types +get_channel_type(struct ccw_device_id *id) +{ + enum channel_types type = (enum channel_types) id->driver_info; + + if (type == channel_type_ficon) + type = channel_type_escon; + + return type; +} + /** * States of the interface statemachine. */ @@ -95,7 +371,7 @@ enum dev_states { /** * MUST be always the last element!! */ - CTC_NR_DEV_STATES + NR_DEV_STATES }; static const char *dev_state_names[] = { @@ -123,7 +399,7 @@ enum dev_events { /** * MUST be always the last element!! */ - CTC_NR_DEV_EVENTS + NR_DEV_EVENTS }; static const char *dev_event_names[] = { @@ -200,6 +476,40 @@ enum ch_events { NR_CH_EVENTS, }; +static const char *ch_event_names[] = { + "ccw_device success", + "ccw_device busy", + "ccw_device enodev", + "ccw_device ioerr", + "ccw_device unknown", + + "Status ATTN & BUSY", + "Status ATTN", + "Status BUSY", + + "Unit check remote reset", + "Unit check remote system reset", + "Unit check TX timeout", + "Unit check TX parity", + "Unit check Hardware failure", + "Unit check RX parity", + "Unit check ZERO", + "Unit check Unknown", + + "SubChannel check Unknown", + + "Machine check failure", + "Machine check operational", + + "IRQ normal", + "IRQ final", + + "Timer", + + "Start", + "Stop", +}; + /** * States of the channel statemachine. */ @@ -235,87 +545,6 @@ enum ch_states { NR_CH_STATES, }; -static int loglevel = CTC_LOGLEVEL_DEFAULT; - -/** - * Linked list of all detected channels. - */ -static struct channel *channels = NULL; - -/** - * Print Banner. - */ -static void -print_banner(void) -{ - static int printed = 0; - char vbuf[] = "$Revision: 1.74 $"; - char *version = vbuf; - - if (printed) - return; - if ((version = strchr(version, ':'))) { - char *p = strchr(version + 1, '$'); - if (p) - *p = '\0'; - } else - version = " ??? "; - printk(KERN_INFO "CTC driver Version%s" -#ifdef DEBUG - " (DEBUG-VERSION, " __DATE__ __TIME__ ")" -#endif - " initialized\n", version); - printed = 1; -} - -/** - * Return type of a detected device. - */ -static enum channel_types -get_channel_type(struct ccw_device_id *id) -{ - enum channel_types type = (enum channel_types) id->driver_info; - - if (type == channel_type_ficon) - type = channel_type_escon; - - return type; -} - -static const char *ch_event_names[] = { - "ccw_device success", - "ccw_device busy", - "ccw_device enodev", - "ccw_device ioerr", - "ccw_device unknown", - - "Status ATTN & BUSY", - "Status ATTN", - "Status BUSY", - - "Unit check remote reset", - "Unit check remote system reset", - "Unit check TX timeout", - "Unit check TX parity", - "Unit check Hardware failure", - "Unit check RX parity", - "Unit check ZERO", - "Unit check Unknown", - - "SubChannel check Unknown", - - "Machine check failure", - "Machine check operational", - - "IRQ normal", - "IRQ final", - - "Timer", - - "Start", - "Stop", -}; - static const char *ch_state_names[] = { "Idle", "Stopped", @@ -1705,6 +1934,7 @@ add_channel(struct ccw_device *cdev, enum channel_types type) ch->cdev = cdev; snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id); ch->type = type; + loglevel = CTC_LOGLEVEL_DEFAULT; ch->fsm = init_fsm(ch->id, ch_state_names, ch_event_names, NR_CH_STATES, NR_CH_EVENTS, ch_fsm, CH_FSM_LEN, GFP_KERNEL); @@ -2467,7 +2697,6 @@ ctc_stats(struct net_device * dev) /* * sysfs attributes */ - static ssize_t buffer_show(struct device *dev, char *buf) { @@ -2486,61 +2715,57 @@ buffer_write(struct device *dev, const char *buf, size_t count) struct ctc_priv *priv; struct net_device *ndev; int bs1; - char buffer[16]; DBF_TEXT(trace, 3, __FUNCTION__); - DBF_TEXT(trace, 3, buf); priv = dev->driver_data; - if (!priv) { - DBF_TEXT(trace, 3, "bfnopriv"); + if (!priv) return -ENODEV; - } - - sscanf(buf, "%u", &bs1); - if (bs1 > CTC_BUFSIZE_LIMIT) - goto einval; - if (bs1 < (576 + LL_HEADER_LENGTH + 2)) - goto einval; - priv->buffer_size = bs1; // just to overwrite the default - ndev = priv->channel[READ]->netdev; - if (!ndev) { - DBF_TEXT(trace, 3, "bfnondev"); + if (!ndev) return -ENODEV; - } + sscanf(buf, "%u", &bs1); + if (bs1 > CTC_BUFSIZE_LIMIT) + return -EINVAL; if ((ndev->flags & IFF_RUNNING) && (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2))) - goto einval; + return -EINVAL; + if (bs1 < (576 + LL_HEADER_LENGTH + 2)) + return -EINVAL; - priv->channel[READ]->max_bufsize = bs1; - priv->channel[WRITE]->max_bufsize = bs1; + priv->buffer_size = bs1; + priv->channel[READ]->max_bufsize = + priv->channel[WRITE]->max_bufsize = bs1; if (!(ndev->flags & IFF_RUNNING)) ndev->mtu = bs1 - LL_HEADER_LENGTH - 2; priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED; - sprintf(buffer, "%d",priv->buffer_size); - DBF_TEXT(trace, 3, buffer); return count; -einval: - DBF_TEXT(trace, 3, "buff_err"); - return -EINVAL; } static ssize_t loglevel_show(struct device *dev, char *buf) { + struct ctc_priv *priv; + + priv = dev->driver_data; + if (!priv) + return -ENODEV; return sprintf(buf, "%d\n", loglevel); } static ssize_t loglevel_write(struct device *dev, const char *buf, size_t count) { + struct ctc_priv *priv; int ll1; DBF_TEXT(trace, 5, __FUNCTION__); + priv = dev->driver_data; + if (!priv) + return -ENODEV; sscanf(buf, "%i", &ll1); if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0)) @@ -2610,6 +2835,27 @@ stats_write(struct device *dev, const char *buf, size_t count) return count; } +static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write); +static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write); +static DEVICE_ATTR(stats, 0644, stats_show, stats_write); + +static int +ctc_add_attributes(struct device *dev) +{ +// device_create_file(dev, &dev_attr_buffer); + device_create_file(dev, &dev_attr_loglevel); + device_create_file(dev, &dev_attr_stats); + return 0; +} + +static void +ctc_remove_attributes(struct device *dev) +{ + device_remove_file(dev, &dev_attr_stats); + device_remove_file(dev, &dev_attr_loglevel); +// device_remove_file(dev, &dev_attr_buffer); +} + static void ctc_netdev_unregister(struct net_device * dev) @@ -2653,6 +2899,52 @@ ctc_free_netdevice(struct net_device * dev, int free_dev) #endif } +/** + * Initialize everything of the net device except the name and the + * channel structs. + */ +static struct net_device * +ctc_init_netdevice(struct net_device * dev, int alloc_device, + struct ctc_priv *privptr) +{ + if (!privptr) + return NULL; + + DBF_TEXT(setup, 3, __FUNCTION__); + if (alloc_device) { + dev = kmalloc(sizeof (struct net_device), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof (struct net_device)); + } + + dev->priv = privptr; + privptr->fsm = init_fsm("ctcdev", dev_state_names, + dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS, + dev_fsm, DEV_FSM_LEN, GFP_KERNEL); + if (privptr->fsm == NULL) { + if (alloc_device) + kfree(dev); + return NULL; + } + fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); + fsm_settimer(privptr->fsm, &privptr->restart_timer); + if (dev->mtu == 0) + dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2; + dev->hard_start_xmit = ctc_tx; + dev->open = ctc_open; + dev->stop = ctc_close; + dev->get_stats = ctc_stats; + dev->change_mtu = ctc_change_mtu; + dev->hard_header_len = LL_HEADER_LENGTH + 2; + dev->addr_len = 0; + dev->type = ARPHRD_SLIP; + dev->tx_queue_len = 100; + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + SET_MODULE_OWNER(dev); + return dev; +} + static ssize_t ctc_proto_show(struct device *dev, char *buf) { @@ -2685,6 +2977,7 @@ ctc_proto_store(struct device *dev, const char *buf, size_t count) return count; } +static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store); static ssize_t ctc_type_show(struct device *dev, char *buf) @@ -2698,13 +2991,8 @@ ctc_type_show(struct device *dev, char *buf) return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]); } -static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write); -static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store); static DEVICE_ATTR(type, 0444, ctc_type_show, NULL); -static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write); -static DEVICE_ATTR(stats, 0644, stats_show, stats_write); - static struct attribute *ctc_attr[] = { &dev_attr_protocol.attr, &dev_attr_type.attr, @@ -2716,21 +3004,6 @@ static struct attribute_group ctc_attr_group = { .attrs = ctc_attr, }; -static int -ctc_add_attributes(struct device *dev) -{ - device_create_file(dev, &dev_attr_loglevel); - device_create_file(dev, &dev_attr_stats); - return 0; -} - -static void -ctc_remove_attributes(struct device *dev) -{ - device_remove_file(dev, &dev_attr_stats); - device_remove_file(dev, &dev_attr_loglevel); -} - static int ctc_add_files(struct device *dev) { @@ -2755,15 +3028,15 @@ ctc_remove_files(struct device *dev) * * @returns 0 on success, !0 on failure. */ + static int ctc_probe_device(struct ccwgroup_device *cgdev) { struct ctc_priv *priv; int rc; - char buffer[16]; pr_debug("%s() called\n", __FUNCTION__); - DBF_TEXT(setup, 3, __FUNCTION__); + DBF_TEXT(trace, 3, __FUNCTION__); if (!get_device(&cgdev->dev)) return -ENODEV; @@ -2787,69 +3060,9 @@ ctc_probe_device(struct ccwgroup_device *cgdev) cgdev->cdev[1]->handler = ctc_irq_handler; cgdev->dev.driver_data = priv; - sprintf(buffer, "%p", priv); - DBF_TEXT(data, 3, buffer); - - sprintf(buffer, "%u", (unsigned int)sizeof(struct ctc_priv)); - DBF_TEXT(data, 3, buffer); - - sprintf(buffer, "%p", &channels); - DBF_TEXT(data, 3, buffer); - - sprintf(buffer, "%u", (unsigned int)sizeof(struct channel)); - DBF_TEXT(data, 3, buffer); - return 0; } -/** - * Initialize everything of the net device except the name and the - * channel structs. - */ -static struct net_device * -ctc_init_netdevice(struct net_device * dev, int alloc_device, - struct ctc_priv *privptr) -{ - if (!privptr) - return NULL; - - DBF_TEXT(setup, 3, __FUNCTION__); - - if (alloc_device) { - dev = kmalloc(sizeof (struct net_device), GFP_KERNEL); - if (!dev) - return NULL; - memset(dev, 0, sizeof (struct net_device)); - } - - dev->priv = privptr; - privptr->fsm = init_fsm("ctcdev", dev_state_names, - dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS, - dev_fsm, DEV_FSM_LEN, GFP_KERNEL); - if (privptr->fsm == NULL) { - if (alloc_device) - kfree(dev); - return NULL; - } - fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); - fsm_settimer(privptr->fsm, &privptr->restart_timer); - if (dev->mtu == 0) - dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2; - dev->hard_start_xmit = ctc_tx; - dev->open = ctc_open; - dev->stop = ctc_close; - dev->get_stats = ctc_stats; - dev->change_mtu = ctc_change_mtu; - dev->hard_header_len = LL_HEADER_LENGTH + 2; - dev->addr_len = 0; - dev->type = ARPHRD_SLIP; - dev->tx_queue_len = 100; - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - SET_MODULE_OWNER(dev); - return dev; -} - - /** * * Setup an interface. @@ -2868,7 +3081,6 @@ ctc_new_device(struct ccwgroup_device *cgdev) struct ctc_priv *privptr; struct net_device *dev; int ret; - char buffer[16]; pr_debug("%s() called\n", __FUNCTION__); DBF_TEXT(setup, 3, __FUNCTION__); @@ -2877,9 +3089,6 @@ ctc_new_device(struct ccwgroup_device *cgdev) if (!privptr) return -ENODEV; - sprintf(buffer, "%d", privptr->buffer_size); - DBF_TEXT(setup, 3, buffer); - type = get_channel_type(&cgdev->cdev[0]->id); snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id); @@ -2968,10 +3177,9 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev) struct ctc_priv *priv; struct net_device *ndev; - DBF_TEXT(setup, 3, __FUNCTION__); + DBF_TEXT(trace, 3, __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__); - priv = cgdev->dev.driver_data; ndev = NULL; if (!priv) @@ -3007,6 +3215,7 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev) channel_remove(priv->channel[READ]); if (priv->channel[WRITE]) channel_remove(priv->channel[WRITE]); + priv->channel[READ] = priv->channel[WRITE] = NULL; return 0; @@ -3019,7 +3228,7 @@ ctc_remove_device(struct ccwgroup_device *cgdev) struct ctc_priv *priv; pr_debug("%s() called\n", __FUNCTION__); - DBF_TEXT(setup, 3, __FUNCTION__); + DBF_TEXT(trace, 3, __FUNCTION__); priv = cgdev->dev.driver_data; if (!priv) @@ -3056,7 +3265,6 @@ static struct ccwgroup_driver ctc_group_driver = { static void __exit ctc_exit(void) { - DBF_TEXT(setup, 3, __FUNCTION__); unregister_cu3088_discipline(&ctc_group_driver); ctc_tty_cleanup(); ctc_unregister_dbf_views(); @@ -3074,10 +3282,6 @@ ctc_init(void) { int ret = 0; - loglevel = CTC_LOGLEVEL_DEFAULT; - - DBF_TEXT(setup, 3, __FUNCTION__); - print_banner(); ret = ctc_register_dbf_views(); diff --git a/trunk/drivers/s390/net/ctcmain.h b/trunk/drivers/s390/net/ctcmain.h deleted file mode 100644 index ba3605f16335..000000000000 --- a/trunk/drivers/s390/net/ctcmain.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * $Id: ctcmain.h,v 1.4 2005/03/24 09:04:17 mschwide Exp $ - * - * CTC / ESCON network driver - * - * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com) - Peter Tiedemann (ptiedem@de.ibm.com) - * - * - * Documentation used: - * - Principles of Operation (IBM doc#: SA22-7201-06) - * - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02) - * - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535) - * - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00) - * - ESCON I/O Interface (IBM doc#: SA22-7202-029 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.4 $ - * - */ - -#ifndef _CTCMAIN_H_ -#define _CTCMAIN_H_ - -#include -#include - -#include "ctctty.h" -#include "fsm.h" -#include "cu3088.h" - - -/** - * CCW commands, used in this driver. - */ -#define CCW_CMD_WRITE 0x01 -#define CCW_CMD_READ 0x02 -#define CCW_CMD_SET_EXTENDED 0xc3 -#define CCW_CMD_PREPARE 0xe3 - -#define CTC_PROTO_S390 0 -#define CTC_PROTO_LINUX 1 -#define CTC_PROTO_LINUX_TTY 2 -#define CTC_PROTO_OS390 3 -#define CTC_PROTO_MAX 3 - -#define CTC_BUFSIZE_LIMIT 65535 -#define CTC_BUFSIZE_DEFAULT 32768 - -#define CTC_TIMEOUT_5SEC 5000 - -#define CTC_INITIAL_BLOCKLEN 2 - -#define READ 0 -#define WRITE 1 - -#define CTC_ID_SIZE BUS_ID_SIZE+3 - - -struct ctc_profile { - unsigned long maxmulti; - unsigned long maxcqueue; - unsigned long doios_single; - unsigned long doios_multi; - unsigned long txlen; - unsigned long tx_time; - struct timespec send_stamp; -}; - -/** - * Definition of one channel - */ -struct channel { - - /** - * Pointer to next channel in list. - */ - struct channel *next; - char id[CTC_ID_SIZE]; - struct ccw_device *cdev; - - /** - * Type of this channel. - * CTC/A or Escon for valid channels. - */ - enum channel_types type; - - /** - * Misc. flags. See CHANNEL_FLAGS_... below - */ - __u32 flags; - - /** - * The protocol of this channel - */ - __u16 protocol; - - /** - * I/O and irq related stuff - */ - struct ccw1 *ccw; - struct irb *irb; - - /** - * RX/TX buffer size - */ - int max_bufsize; - - /** - * Transmit/Receive buffer. - */ - struct sk_buff *trans_skb; - - /** - * Universal I/O queue. - */ - struct sk_buff_head io_queue; - - /** - * TX queue for collecting skb's during busy. - */ - struct sk_buff_head collect_queue; - - /** - * Amount of data in collect_queue. - */ - int collect_len; - - /** - * spinlock for collect_queue and collect_len - */ - spinlock_t collect_lock; - - /** - * Timer for detecting unresposive - * I/O operations. - */ - fsm_timer timer; - - /** - * Retry counter for misc. operations. - */ - int retry; - - /** - * The finite state machine of this channel - */ - fsm_instance *fsm; - - /** - * The corresponding net_device this channel - * belongs to. - */ - struct net_device *netdev; - - struct ctc_profile prof; - - unsigned char *trans_skb_data; - - __u16 logflags; -}; - -#define CHANNEL_FLAGS_READ 0 -#define CHANNEL_FLAGS_WRITE 1 -#define CHANNEL_FLAGS_INUSE 2 -#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4 -#define CHANNEL_FLAGS_FAILED 8 -#define CHANNEL_FLAGS_WAITIRQ 16 -#define CHANNEL_FLAGS_RWMASK 1 -#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK) - -#define LOG_FLAG_ILLEGALPKT 1 -#define LOG_FLAG_ILLEGALSIZE 2 -#define LOG_FLAG_OVERRUN 4 -#define LOG_FLAG_NOMEM 8 - -#define CTC_LOGLEVEL_INFO 1 -#define CTC_LOGLEVEL_NOTICE 2 -#define CTC_LOGLEVEL_WARN 4 -#define CTC_LOGLEVEL_EMERG 8 -#define CTC_LOGLEVEL_ERR 16 -#define CTC_LOGLEVEL_DEBUG 32 -#define CTC_LOGLEVEL_CRIT 64 - -#define CTC_LOGLEVEL_DEFAULT \ -(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT) - -#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1) - -#define ctc_pr_debug(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0) - -#define ctc_pr_info(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0) - -#define ctc_pr_notice(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0) - -#define ctc_pr_warn(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0) - -#define ctc_pr_emerg(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0) - -#define ctc_pr_err(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0) - -#define ctc_pr_crit(fmt, arg...) \ -do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0) - -struct ctc_priv { - struct net_device_stats stats; - unsigned long tbusy; - /** - * The finite state machine of this interface. - */ - fsm_instance *fsm; - /** - * The protocol of this device - */ - __u16 protocol; - /** - * Timer for restarting after I/O Errors - */ - fsm_timer restart_timer; - - int buffer_size; - - struct channel *channel[2]; -}; - -/** - * Definition of our link level header. - */ -struct ll_header { - __u16 length; - __u16 type; - __u16 unused; -}; -#define LL_HEADER_LENGTH (sizeof(struct ll_header)) - -/** - * Compatibility macros for busy handling - * of network devices. - */ -static __inline__ void -ctc_clear_busy(struct net_device * dev) -{ - clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy)); - if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) - netif_wake_queue(dev); -} - -static __inline__ int -ctc_test_and_set_busy(struct net_device * dev) -{ - if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) - netif_stop_queue(dev); - return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy); -} - -#endif diff --git a/trunk/drivers/s390/net/ctctty.c b/trunk/drivers/s390/net/ctctty.c index 3080393e823d..9257d60c7833 100644 --- a/trunk/drivers/s390/net/ctctty.c +++ b/trunk/drivers/s390/net/ctctty.c @@ -1,5 +1,5 @@ /* - * $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $ + * $Id: ctctty.c,v 1.26 2004/08/04 11:06:55 mschwide Exp $ * * CTC / ESCON network driver, tty interface. * @@ -1056,7 +1056,8 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp) info->tty = 0; tty->closing = 0; if (info->blocked_open) { - msleep_interruptible(500); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/2); wake_up_interruptible(&info->open_wait); } info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING); diff --git a/trunk/drivers/s390/net/cu3088.c b/trunk/drivers/s390/net/cu3088.c index 0075894c71db..1b0a9f16024c 100644 --- a/trunk/drivers/s390/net/cu3088.c +++ b/trunk/drivers/s390/net/cu3088.c @@ -1,5 +1,5 @@ /* - * $Id: cu3088.c,v 1.35 2005/03/30 19:28:52 richtera Exp $ + * $Id: cu3088.c,v 1.34 2004/06/15 13:16:27 pavlic Exp $ * * CTC / LCS ccw_device driver * @@ -39,7 +39,6 @@ const char *cu3088_type[] = { "FICON channel", "P390 LCS card", "OSA LCS card", - "CLAW channel device", "unknown channel type", "unsupported channel type", }; @@ -52,7 +51,6 @@ static struct ccw_device_id cu3088_ids[] = { { CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon }, { CCW_DEVICE(0x3088, 0x01), .driver_info = channel_type_p390 }, { CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 }, - { CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw }, { /* end of list */ } }; diff --git a/trunk/drivers/s390/net/cu3088.h b/trunk/drivers/s390/net/cu3088.h index 1753661f702a..0ec49a8b3adc 100644 --- a/trunk/drivers/s390/net/cu3088.h +++ b/trunk/drivers/s390/net/cu3088.h @@ -23,9 +23,6 @@ enum channel_types { /* Device is a OSA2 card */ channel_type_osa2, - /* Device is a CLAW channel device */ - channel_type_claw, - /* Device is a channel, but we don't know * anything about it */ channel_type_unknown, diff --git a/trunk/drivers/s390/net/iucv.c b/trunk/drivers/s390/net/iucv.c index e08e74e16124..1ac6563ee3e0 100644 --- a/trunk/drivers/s390/net/iucv.c +++ b/trunk/drivers/s390/net/iucv.c @@ -1,5 +1,5 @@ /* - * $Id: iucv.c,v 1.45 2005/04/26 22:59:06 braunu Exp $ + * $Id: iucv.c,v 1.43 2005/02/09 14:47:43 braunu Exp $ * * IUCV network driver * @@ -29,7 +29,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.45 $ + * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.43 $ * */ @@ -355,7 +355,7 @@ do { \ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.45 $"; + char vbuf[] = "$Revision: 1.43 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { @@ -2553,12 +2553,12 @@ EXPORT_SYMBOL (iucv_resume); #endif EXPORT_SYMBOL (iucv_reply_prmmsg); EXPORT_SYMBOL (iucv_send); +#if 0 EXPORT_SYMBOL (iucv_send2way); EXPORT_SYMBOL (iucv_send2way_array); +EXPORT_SYMBOL (iucv_send_array); EXPORT_SYMBOL (iucv_send2way_prmmsg); EXPORT_SYMBOL (iucv_send2way_prmmsg_array); -#if 0 -EXPORT_SYMBOL (iucv_send_array); EXPORT_SYMBOL (iucv_send_prmmsg); EXPORT_SYMBOL (iucv_setmask); #endif diff --git a/trunk/drivers/s390/net/lcs.c b/trunk/drivers/s390/net/lcs.c index cccfed248e70..0f76e945b984 100644 --- a/trunk/drivers/s390/net/lcs.c +++ b/trunk/drivers/s390/net/lcs.c @@ -11,7 +11,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Martin Schwidefsky * - * $Revision: 1.98 $ $Date: 2005/04/18 13:41:29 $ + * $Revision: 1.96 $ $Date: 2004/11/11 13:42:33 $ * * 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 @@ -59,7 +59,7 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.98 $" +#define VERSION_LCS_C "$Revision: 1.96 $" static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; static char debug_buffer[255]; @@ -1098,6 +1098,14 @@ lcs_check_multicast_support(struct lcs_card *card) PRINT_ERR("Query IPAssist failed. Assuming unsupported!\n"); return -EOPNOTSUPP; } + /* Print out supported assists: IPv6 */ + PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name, + (card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ? + "with" : "without"); + /* Print out supported assist: Multicast */ + PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name, + (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ? + "with" : "without"); if (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) return 0; return -EOPNOTSUPP; @@ -1152,7 +1160,7 @@ lcs_fix_multicast_list(struct lcs_card *card) } } /* re-insert all entries from the failed_list into ipm_list */ - list_for_each_entry_safe(ipm, tmp, &failed_list, list) { + list_for_each_entry(ipm, &failed_list, list) { list_del_init(&ipm->list); list_add_tail(&ipm->list, &card->ipm_list); } @@ -2190,39 +2198,30 @@ lcs_new_device(struct ccwgroup_device *ccwgdev) if (!dev) goto out; card->dev = dev; +netdev_out: card->dev->priv = card; card->dev->open = lcs_open_device; card->dev->stop = lcs_stop_device; card->dev->hard_start_xmit = lcs_start_xmit; card->dev->get_stats = lcs_getstats; SET_MODULE_OWNER(dev); + if (lcs_register_netdev(ccwgdev) != 0) + goto out; memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH); #ifdef CONFIG_IP_MULTICAST if (!lcs_check_multicast_support(card)) card->dev->set_multicast_list = lcs_set_multicast_list; #endif -netdev_out: + netif_stop_queue(card->dev); lcs_set_allowed_threads(card,0xffffffff); if (recover_state == DEV_STATE_RECOVER) { lcs_set_multicast_list(card->dev); card->dev->flags |= IFF_UP; netif_wake_queue(card->dev); card->state = DEV_STATE_UP; - } else { + } else lcs_stopcard(card); - } - if (lcs_register_netdev(ccwgdev) != 0) - goto out; - - /* Print out supported assists: IPv6 */ - PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name, - (card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ? - "with" : "without"); - /* Print out supported assist: Multicast */ - PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name, - (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ? - "with" : "without"); return 0; out: diff --git a/trunk/drivers/s390/net/qeth.h b/trunk/drivers/s390/net/qeth.h index a755b57db46b..a341041a6cf7 100644 --- a/trunk/drivers/s390/net/qeth.h +++ b/trunk/drivers/s390/net/qeth.h @@ -24,7 +24,7 @@ #include "qeth_mpc.h" -#define VERSION_QETH_H "$Revision: 1.139 $" +#define VERSION_QETH_H "$Revision: 1.135 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -288,8 +288,7 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func) #define QETH_TX_TIMEOUT 100 * HZ #define QETH_HEADER_SIZE 32 #define MAX_PORTNO 15 -#define QETH_FAKE_LL_LEN_ETH ETH_HLEN -#define QETH_FAKE_LL_LEN_TR (sizeof(struct trh_hdr)-TR_MAXRIFLEN+sizeof(struct trllc)) +#define QETH_FAKE_LL_LEN ETH_HLEN #define QETH_FAKE_LL_V6_ADDR_POS 24 /*IPv6 address autoconfiguration stuff*/ @@ -370,25 +369,6 @@ struct qeth_hdr { } hdr; } __attribute__ ((packed)); -/*TCP Segmentation Offload header*/ -struct qeth_hdr_ext_tso { - __u16 hdr_tot_len; - __u8 imb_hdr_no; - __u8 reserved; - __u8 hdr_type; - __u8 hdr_version; - __u16 hdr_len; - __u32 payload_len; - __u16 mss; - __u16 dg_hdr_len; - __u8 padding[16]; -} __attribute__ ((packed)); - -struct qeth_hdr_tso { - struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/ - struct qeth_hdr_ext_tso ext; -} __attribute__ ((packed)); - /* flags for qeth_hdr.flags */ #define QETH_HDR_PASSTHRU 0x10 @@ -886,7 +866,6 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size) return hdr; } - inline static int qeth_get_hlen(__u8 link_type) { @@ -894,19 +873,19 @@ qeth_get_hlen(__u8 link_type) switch (link_type) { case QETH_LINK_TYPE_HSTR: case QETH_LINK_TYPE_LANE_TR: - return sizeof(struct qeth_hdr_tso) + TR_HLEN; + return sizeof(struct qeth_hdr) + TR_HLEN; default: #ifdef CONFIG_QETH_VLAN - return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN; + return sizeof(struct qeth_hdr) + VLAN_ETH_HLEN; #else - return sizeof(struct qeth_hdr_tso) + ETH_HLEN; + return sizeof(struct qeth_hdr) + ETH_HLEN; #endif } #else /* CONFIG_QETH_IPV6 */ #ifdef CONFIG_QETH_VLAN - return sizeof(struct qeth_hdr_tso) + VLAN_HLEN; + return sizeof(struct qeth_hdr) + VLAN_HLEN; #else - return sizeof(struct qeth_hdr_tso); + return sizeof(struct qeth_hdr); #endif #endif /* CONFIG_QETH_IPV6 */ } diff --git a/trunk/drivers/s390/net/qeth_eddp.c b/trunk/drivers/s390/net/qeth_eddp.c index f94f1f25eec6..7ee1c06ed68a 100644 --- a/trunk/drivers/s390/net/qeth_eddp.c +++ b/trunk/drivers/s390/net/qeth_eddp.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $) + * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.11 $) * * Enhanced Device Driver Packing (EDDP) support for the qeth driver. * @@ -8,7 +8,7 @@ * * Author(s): Thomas Spatzier * - * $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.11 $ $Date: 2005/03/24 09:04:18 $ * */ #include @@ -85,7 +85,7 @@ void qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf) { struct qeth_eddp_context_reference *ref; - + QETH_DBF_TEXT(trace, 6, "eddprctx"); while (!list_empty(&buf->ctx_list)){ ref = list_entry(buf->ctx_list.next, @@ -139,7 +139,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, "buffer!\n"); goto out; } - } + } /* check if the whole next skb fits into current buffer */ if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) - buf->next_element_to_fill) @@ -152,7 +152,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, * and increment ctx's refcnt */ must_refcnt = 1; continue; - } + } if (must_refcnt){ must_refcnt = 0; if (qeth_eddp_buf_ref_context(buf, ctx)){ @@ -202,29 +202,40 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, return flush_cnt; } +static inline int +qeth_get_skb_data_len(struct sk_buff *skb) +{ + int len = skb->len; + int i; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) + len -= skb_shinfo(skb)->frags[i].size; + return len; +} + static inline void qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, - struct qeth_eddp_data *eddp, int data_len) + struct qeth_eddp_data *eddp) { u8 *page; int page_remainder; int page_offset; - int pkt_len; + int hdr_len; struct qeth_eddp_element *element; QETH_DBF_TEXT(trace, 5, "eddpcrsh"); page = ctx->pages[ctx->offset >> PAGE_SHIFT]; page_offset = ctx->offset % PAGE_SIZE; element = &ctx->elements[ctx->num_elements]; - pkt_len = eddp->nhl + eddp->thl + data_len; + hdr_len = eddp->nhl + eddp->thl; /* FIXME: layer2 and VLAN !!! */ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) - pkt_len += ETH_HLEN; + hdr_len += ETH_HLEN; if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) - pkt_len += VLAN_HLEN; - /* does complete packet fit in current page ? */ + hdr_len += VLAN_HLEN; + /* does complete header fit in current page ? */ page_remainder = PAGE_SIZE - page_offset; - if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){ + if (page_remainder < (sizeof(struct qeth_hdr) + hdr_len)){ /* no -> go to start of next page */ ctx->offset += page_remainder; page = ctx->pages[ctx->offset >> PAGE_SHIFT]; @@ -270,7 +281,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, int left_in_frag; int copy_len; u8 *src; - + QETH_DBF_TEXT(trace, 5, "eddpcdtc"); if (skb_shinfo(eddp->skb)->nr_frags == 0) { memcpy(dst, eddp->skb->data + eddp->skb_offset, len); @@ -281,7 +292,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, while (len > 0) { if (eddp->frag < 0) { /* we're in skb->data */ - left_in_frag = (eddp->skb->len - eddp->skb->data_len) + left_in_frag = qeth_get_skb_data_len(eddp->skb) - eddp->skb_offset; src = eddp->skb->data + eddp->skb_offset; } else { @@ -413,7 +424,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, struct tcphdr *tcph; int data_len; u32 hcsum; - + QETH_DBF_TEXT(trace, 5, "eddpftcp"); eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; tcph = eddp->skb->h.th; @@ -453,7 +464,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, else hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len); /* fill the next segment into the context */ - qeth_eddp_create_segment_hdrs(ctx, eddp, data_len); + qeth_eddp_create_segment_hdrs(ctx, eddp); qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum); if (eddp->skb_offset >= eddp->skb->len) break; @@ -463,13 +474,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, eddp->th.tcp.h.seq += data_len; } } - + static inline int qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, struct sk_buff *skb, struct qeth_hdr *qhdr) { struct qeth_eddp_data *eddp = NULL; - + QETH_DBF_TEXT(trace, 5, "eddpficx"); /* create our segmentation headers and copy original headers */ if (skb->protocol == ETH_P_IP) @@ -509,7 +520,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb, int hdr_len) { int skbs_per_page; - + QETH_DBF_TEXT(trace, 5, "eddpcanp"); /* can we put multiple skbs in one page? */ skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len); @@ -589,7 +600,7 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *qhdr) { struct qeth_eddp_context *ctx = NULL; - + QETH_DBF_TEXT(trace, 5, "creddpct"); if (skb->protocol == ETH_P_IP) ctx = qeth_eddp_create_context_generic(card, skb, diff --git a/trunk/drivers/s390/net/qeth_main.c b/trunk/drivers/s390/net/qeth_main.c index 208127a5033a..607b92542df6 100644 --- a/trunk/drivers/s390/net/qeth_main.c +++ b/trunk/drivers/s390/net/qeth_main.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $) + * linux/drivers/s390/net/qeth_main.c ($Revision: 1.206 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier * - * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.206 $ $Date: 2005/03/24 09:04:18 $ * * 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 @@ -80,7 +80,7 @@ qeth_eyecatcher(void) #include "qeth_eddp.h" #include "qeth_tso.h" -#define VERSION_QETH_C "$Revision: 1.214 $" +#define VERSION_QETH_C "$Revision: 1.206 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -158,9 +158,6 @@ qeth_irq_tasklet(unsigned long); static int qeth_set_online(struct ccwgroup_device *); -static int -__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode); - static struct qeth_ipaddr * qeth_get_addr_buffer(enum qeth_prot_versions); @@ -513,10 +510,10 @@ qeth_irq_tasklet(unsigned long data) wake_up(&card->wait_q); } -static int qeth_stop_card(struct qeth_card *, int); +static int qeth_stop_card(struct qeth_card *); static int -__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) +qeth_set_offline(struct ccwgroup_device *cgdev) { struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data; int rc = 0; @@ -526,7 +523,7 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) QETH_DBF_HEX(setup, 3, &card, sizeof(void *)); recover_flag = card->state; - if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){ + if (qeth_stop_card(card) == -ERESTARTSYS){ PRINT_WARN("Stopping card %s interrupted by user!\n", CARD_BUS_ID(card)); return -ERESTARTSYS; @@ -542,12 +539,6 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) return 0; } -static int -qeth_set_offline(struct ccwgroup_device *cgdev) -{ - return __qeth_set_offline(cgdev, 0); -} - static int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads); @@ -962,8 +953,8 @@ qeth_recover(void *ptr) PRINT_WARN("Recovery of device %s started ...\n", CARD_BUS_ID(card)); card->use_hard_stop = 1; - __qeth_set_offline(card->gdev,1); - rc = __qeth_set_online(card->gdev,1); + qeth_set_offline(card->gdev); + rc = qeth_set_online(card->gdev); if (!rc) PRINT_INFO("Device %s successfully recovered!\n", CARD_BUS_ID(card)); @@ -2161,15 +2152,9 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, if (!skb_len) return NULL; if (card->options.fake_ll){ - if(card->dev->type == ARPHRD_IEEE802_TR){ - if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR))) - goto no_mem; - skb_reserve(skb,QETH_FAKE_LL_LEN_TR); - } else { - if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH))) - goto no_mem; - skb_reserve(skb,QETH_FAKE_LL_LEN_ETH); - } + if (!(skb = qeth_get_skb(skb_len + QETH_FAKE_LL_LEN))) + goto no_mem; + skb_pull(skb, QETH_FAKE_LL_LEN); } else if (!(skb = qeth_get_skb(skb_len))) goto no_mem; data_ptr = element->addr + offset; @@ -2244,68 +2229,14 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev) } static inline void -qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb, - struct qeth_hdr *hdr) -{ - struct trh_hdr *fake_hdr; - struct trllc *fake_llc; - struct iphdr *ip_hdr; - - QETH_DBF_TEXT(trace,5,"skbfktr"); - skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_TR; - /* this is a fake ethernet header */ - fake_hdr = (struct trh_hdr *) skb->mac.raw; - - /* the destination MAC address */ - switch (skb->pkt_type){ - case PACKET_MULTICAST: - switch (skb->protocol){ -#ifdef CONFIG_QETH_IPV6 - case __constant_htons(ETH_P_IPV6): - ndisc_mc_map((struct in6_addr *) - skb->data + QETH_FAKE_LL_V6_ADDR_POS, - fake_hdr->daddr, card->dev, 0); - break; -#endif /* CONFIG_QETH_IPV6 */ - case __constant_htons(ETH_P_IP): - ip_hdr = (struct iphdr *)skb->data; - ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr); - break; - default: - memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN); - } - break; - case PACKET_BROADCAST: - memset(fake_hdr->daddr, 0xff, TR_ALEN); - break; - default: - memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN); - } - /* the source MAC address */ - if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) - memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN); - else - memset(fake_hdr->saddr, 0, TR_ALEN); - fake_hdr->rcf=0; - fake_llc = (struct trllc*)&(fake_hdr->rcf); - fake_llc->dsap = EXTENDED_SAP; - fake_llc->ssap = EXTENDED_SAP; - fake_llc->llc = UI_CMD; - fake_llc->protid[0] = 0; - fake_llc->protid[1] = 0; - fake_llc->protid[2] = 0; - fake_llc->ethertype = ETH_P_IP; -} - -static inline void -qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb, +qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) { struct ethhdr *fake_hdr; struct iphdr *ip_hdr; - QETH_DBF_TEXT(trace,5,"skbfketh"); - skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_ETH; + QETH_DBF_TEXT(trace,5,"skbfake"); + skb->mac.raw = skb->data - QETH_FAKE_LL_LEN; /* this is a fake ethernet header */ fake_hdr = (struct ethhdr *) skb->mac.raw; @@ -2322,7 +2253,10 @@ qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb, #endif /* CONFIG_QETH_IPV6 */ case __constant_htons(ETH_P_IP): ip_hdr = (struct iphdr *)skb->data; - ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest); + if (card->dev->type == ARPHRD_IEEE802_TR) + ip_tr_mc_map(ip_hdr->daddr, fake_hdr->h_dest); + else + ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest); break; default: memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN); @@ -2343,16 +2277,6 @@ qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb, fake_hdr->h_proto = skb->protocol; } -static inline void -qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, - struct qeth_hdr *hdr) -{ - if (card->dev->type == ARPHRD_IEEE802_TR) - qeth_rebuild_skb_fake_ll_tr(card, skb, hdr); - else - qeth_rebuild_skb_fake_ll_eth(card, skb, hdr); -} - static inline void qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) @@ -3516,25 +3440,16 @@ qeth_fake_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { - if(dev->type == ARPHRD_IEEE802_TR){ - struct trh_hdr *hdr; - hdr = (struct trh_hdr *)skb_push(skb, QETH_FAKE_LL_LEN_TR); - memcpy(hdr->saddr, dev->dev_addr, TR_ALEN); - memcpy(hdr->daddr, "FAKELL", TR_ALEN); - return QETH_FAKE_LL_LEN_TR; - - } else { - struct ethhdr *hdr; - hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN_ETH); - memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN); - memcpy(hdr->h_dest, "FAKELL", ETH_ALEN); - if (type != ETH_P_802_3) - hdr->h_proto = htons(type); - else - hdr->h_proto = htons(len); - return QETH_FAKE_LL_LEN_ETH; + struct ethhdr *hdr; - } + hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN); + memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN); + memcpy(hdr->h_dest, "FAKELL", ETH_ALEN); + if (type != ETH_P_802_3) + hdr->h_proto = htons(type); + else + hdr->h_proto = htons(len); + return QETH_FAKE_LL_LEN; } static inline int @@ -3795,12 +3710,16 @@ static inline int qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, struct qeth_hdr **hdr, int ipv) { + int rc = 0; #ifdef CONFIG_QETH_VLAN u16 *tag; #endif QETH_DBF_TEXT(trace, 6, "prepskb"); + rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); + if (rc) + return rc; #ifdef CONFIG_QETH_VLAN if (card->vlangrp && vlan_tx_tag_present(*skb) && ((ipv == 6) || card->options.layer2) ) { @@ -3963,15 +3882,9 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, memcpy(hdr->hdr.l3.dest_addr, &skb->nh.ipv6h->daddr, 16); } } else { /* passthrough */ - if((skb->dev->type == ARPHRD_IEEE802_TR) && - !memcmp(skb->data + sizeof(struct qeth_hdr) + - sizeof(__u16), skb->dev->broadcast, 6)) { - hdr->hdr.l3.flags = QETH_CAST_BROADCAST | - QETH_HDR_PASSTHRU; - } else if (!memcmp(skb->data + sizeof(struct qeth_hdr), + if (!memcmp(skb->data + sizeof(struct qeth_hdr), skb->dev->broadcast, 6)) { /* broadcast? */ - hdr->hdr.l3.flags = QETH_CAST_BROADCAST | - QETH_HDR_PASSTHRU; + hdr->hdr.l3.flags = QETH_CAST_BROADCAST | QETH_HDR_PASSTHRU; } else { hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ? QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU : @@ -3980,30 +3893,68 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, } } +static inline void +__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer, + int *next_element_to_fill) +{ + int length = skb->len; + struct skb_frag_struct *frag; + int fragno; + unsigned long addr; + int element; + int first_lap = 1; + + fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */ + element = *next_element_to_fill + fragno; + while (length > 0) { + if (fragno > 0) { + frag = &skb_shinfo(skb)->frags[fragno - 1]; + addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + + frag->page_offset; + buffer->element[element].addr = (char *)addr; + buffer->element[element].length = frag->size; + length -= frag->size; + if (first_lap) + buffer->element[element].flags = + SBAL_FLAGS_LAST_FRAG; + else + buffer->element[element].flags = + SBAL_FLAGS_MIDDLE_FRAG; + } else { + buffer->element[element].addr = skb->data; + buffer->element[element].length = length; + length = 0; + buffer->element[element].flags = + SBAL_FLAGS_FIRST_FRAG; + } + element--; + fragno--; + first_lap = 0; + } + *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1; +} + static inline void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, - int is_tso, int *next_element_to_fill) + int *next_element_to_fill) { int length = skb->len; int length_here; int element; char *data; - int first_lap ; + int first_lap = 1; element = *next_element_to_fill; data = skb->data; - first_lap = (is_tso == 0 ? 1 : 0); - while (length > 0) { /* length_here is the remaining amount of data in this page */ length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); if (length < length_here) length_here = length; - buffer->element[element].addr = data; buffer->element[element].length = length_here; length -= length_here; - if (!length) { + if (!length){ if (first_lap) buffer->element[element].flags = 0; else @@ -4030,35 +3981,17 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, struct sk_buff *skb) { struct qdio_buffer *buffer; - struct qeth_hdr_tso *hdr; - int flush_cnt = 0, hdr_len, large_send = 0; + int flush_cnt = 0; QETH_DBF_TEXT(trace, 6, "qdfillbf"); - buffer = buf->buffer; atomic_inc(&skb->users); skb_queue_tail(&buf->skb_list, skb); - - hdr = (struct qeth_hdr_tso *) skb->data; - /*check first on TSO ....*/ - if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) { - int element = buf->next_element_to_fill; - - hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len; - /*fill first buffer entry only with header information */ - buffer->element[element].addr = skb->data; - buffer->element[element].length = hdr_len; - buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; - buf->next_element_to_fill++; - skb->data += hdr_len; - skb->len -= hdr_len; - large_send = 1; - } if (skb_shinfo(skb)->nr_frags == 0) - __qeth_fill_buffer(skb, buffer, large_send, + __qeth_fill_buffer(skb, buffer, (int *)&buf->next_element_to_fill); else - __qeth_fill_buffer_frag(skb, buffer, large_send, + __qeth_fill_buffer_frag(skb, buffer, (int *)&buf->next_element_to_fill); if (!queue->do_pack) { @@ -4250,25 +4183,6 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, return rc; } -static inline int -qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) -{ - int elements_needed = 0; - - if (skb_shinfo(skb)->nr_frags > 0) { - elements_needed = (skb_shinfo(skb)->nr_frags + 1); - } - if (elements_needed == 0 ) - elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) - + skb->len) >> PAGE_SHIFT); - if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ - PRINT_ERR("qeth_do_send_packet: invalid size of " - "IP packet. Discarded."); - return 0; - } - return elements_needed; -} - static inline int qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) { @@ -4291,11 +4205,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) dev_kfree_skb_irq(skb); return 0; } - if(card->dev->type == ARPHRD_IEEE802_TR){ - skb_pull(skb, QETH_FAKE_LL_LEN_TR); - } else { - skb_pull(skb, QETH_FAKE_LL_LEN_ETH); - } + skb_pull(skb, QETH_FAKE_LL_LEN); } } cast_type = qeth_get_cast_type(card, skb); @@ -4311,25 +4221,19 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) if (skb_shinfo(skb)->tso_size) large_send = card->options.large_send; + if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))){ + QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); + return rc; + } /*are we able to do TSO ? If so ,prepare and send it from here */ if ((large_send == QETH_LARGE_SEND_TSO) && (cast_type == RTN_UNSPEC)) { - rc = qeth_tso_prepare_packet(card, skb, ipv, cast_type); - if (rc) { - card->stats.tx_dropped++; - card->stats.tx_errors++; - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - elements_needed++; - } else { - if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) { - QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); - return rc; - } - qeth_fill_header(card, hdr, skb, ipv, cast_type); + rc = qeth_tso_send_packet(card, skb, queue, + ipv, cast_type); + goto do_statistics; } + qeth_fill_header(card, hdr, skb, ipv, cast_type); if (large_send == QETH_LARGE_SEND_EDDP) { ctx = qeth_eddp_create_context(card, skb, hdr); if (ctx == NULL) { @@ -4337,7 +4241,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) return -EINVAL; } } else { - elements_needed += qeth_get_elements_no(card,(void*) hdr, skb); + elements_needed = qeth_get_elements_no(card,(void*) hdr, skb); if (!elements_needed) return -EINVAL; } @@ -4348,12 +4252,12 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) else rc = qeth_do_send_packet_fast(card, queue, skb, hdr, elements_needed, ctx); +do_statistics: if (!rc){ card->stats.tx_packets++; card->stats.tx_bytes += skb->len; #ifdef CONFIG_QETH_PERF_STATS - if (skb_shinfo(skb)->tso_size && - !(large_send == QETH_LARGE_SEND_NO)) { + if (skb_shinfo(skb)->tso_size) { card->perf_stats.large_send_bytes += skb->len; card->perf_stats.large_send_cnt++; } @@ -7250,7 +7154,7 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads) } static int -qeth_stop_card(struct qeth_card *card, int recovery_mode) +qeth_stop_card(struct qeth_card *card) { int rc = 0; @@ -7263,13 +7167,9 @@ qeth_stop_card(struct qeth_card *card, int recovery_mode) if (card->read.state == CH_STATE_UP && card->write.state == CH_STATE_UP && (card->state == CARD_STATE_UP)) { - if(recovery_mode) { - qeth_stop(card->dev); - } else { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); if (!card->use_hard_stop) { __u8 *mac = &card->dev->dev_addr[0]; rc = qeth_layer2_send_delmac(card, mac); @@ -7441,17 +7341,13 @@ qeth_register_netdev(struct qeth_card *card) } static void -qeth_start_again(struct qeth_card *card, int recovery_mode) +qeth_start_again(struct qeth_card *card) { QETH_DBF_TEXT(setup ,2, "startag"); - if(recovery_mode) { - qeth_open(card->dev); - } else { - rtnl_lock(); - dev_open(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_open(card->dev); + rtnl_unlock(); /* this also sets saved unicast addresses */ qeth_set_multicast_list(card->dev); } @@ -7508,7 +7404,7 @@ static void qeth_make_parameters_consistent(struct qeth_card *card) static int -__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) +qeth_set_online(struct ccwgroup_device *gdev) { struct qeth_card *card = gdev->dev.driver_data; int rc = 0; @@ -7568,12 +7464,12 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) * we can also use this state for recovery purposes*/ qeth_set_allowed_threads(card, 0xffffffff, 0); if (recover_flag == CARD_STATE_RECOVER) - qeth_start_again(card, recovery_mode); + qeth_start_again(card); qeth_notify_processes(); return 0; out_remove: card->use_hard_stop = 1; - qeth_stop_card(card, 0); + qeth_stop_card(card); ccw_device_set_offline(CARD_DDEV(card)); ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_RDEV(card)); @@ -7584,12 +7480,6 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) return -ENODEV; } -static int -qeth_set_online(struct ccwgroup_device *gdev) -{ - return __qeth_set_online(gdev, 0); -} - static struct ccw_device_id qeth_ids[] = { {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE}, {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD}, diff --git a/trunk/drivers/s390/net/qeth_tso.c b/trunk/drivers/s390/net/qeth_tso.c new file mode 100644 index 000000000000..c91976274e7b --- /dev/null +++ b/trunk/drivers/s390/net/qeth_tso.c @@ -0,0 +1,285 @@ +/* + * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.6 $) + * + * Header file for qeth TCP Segmentation Offload support. + * + * Copyright 2004 IBM Corporation + * + * Author(s): Frank Pavlic + * + * $Revision: 1.6 $ $Date: 2005/03/24 09:04:18 $ + * + */ + +#include +#include +#include +#include +#include +#include "qeth.h" +#include "qeth_mpc.h" +#include "qeth_tso.h" + +/** + * skb already partially prepared + * classic qdio header in skb->data + * */ +static inline struct qeth_hdr_tso * +qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb) +{ + int rc = 0; + + QETH_DBF_TEXT(trace, 5, "tsoprsk"); + rc = qeth_realloc_headroom(card, skb,sizeof(struct qeth_hdr_ext_tso)); + if (rc) + return NULL; + + return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_ext_tso)); +} + +/** + * fill header for a TSO packet + */ +static inline void +qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb) +{ + struct qeth_hdr_tso *hdr; + struct tcphdr *tcph; + struct iphdr *iph; + + QETH_DBF_TEXT(trace, 5, "tsofhdr"); + + hdr = (struct qeth_hdr_tso *) skb->data; + iph = skb->nh.iph; + tcph = skb->h.th; + /*fix header to TSO values ...*/ + hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; + /*set values which are fix for the first approach ...*/ + hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); + hdr->ext.imb_hdr_no = 1; + hdr->ext.hdr_type = 1; + hdr->ext.hdr_version = 1; + hdr->ext.hdr_len = 28; + /*insert non-fix values */ + hdr->ext.mss = skb_shinfo(skb)->tso_size; + hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); + hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - + sizeof(struct qeth_hdr_tso)); +} + +/** + * change some header values as requested by hardware + */ +static inline void +qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb) +{ + struct iphdr *iph; + struct ipv6hdr *ip6h; + struct tcphdr *tcph; + + iph = skb->nh.iph; + ip6h = skb->nh.ipv6h; + tcph = skb->h.th; + + tcph->check = 0; + if (skb->protocol == ETH_P_IPV6) { + ip6h->payload_len = 0; + tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + 0, IPPROTO_TCP, 0); + return; + } + /*OSA want us to set these values ...*/ + tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, + 0, IPPROTO_TCP, 0); + iph->tot_len = 0; + iph->check = 0; +} + +static inline struct qeth_hdr_tso * +qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb, + int ipv, int cast_type) +{ + struct qeth_hdr_tso *hdr; + int rc = 0; + + QETH_DBF_TEXT(trace, 5, "tsoprep"); + + /*get headroom for tso qdio header */ + hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb); + if (hdr == NULL) { + QETH_DBF_TEXT_(trace, 4, "2err%d", rc); + return NULL; + } + memset(hdr, 0, sizeof(struct qeth_hdr_tso)); + /*fill first 32 bytes of qdio header as used + *FIXME: TSO has two struct members + * with different names but same size + * */ + qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type); + qeth_tso_fill_header(card, skb); + qeth_tso_set_tcpip_header(card, skb); + return hdr; +} + +static inline int +qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue) +{ + struct qeth_qdio_out_buffer *buffer; + int flush_cnt = 0; + + QETH_DBF_TEXT(trace, 5, "tsobuf"); + + /* force to non-packing*/ + if (queue->do_pack) + queue->do_pack = 0; + buffer = &queue->bufs[queue->next_buf_to_fill]; + /* get a new buffer if current is already in use*/ + if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) && + (buffer->next_element_to_fill > 0)) { + atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED); + queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % + QDIO_MAX_BUFFERS_PER_Q; + flush_cnt++; + } + return flush_cnt; +} + +static inline void +__qeth_tso_fill_buffer_frag(struct qeth_qdio_out_buffer *buf, + struct sk_buff *skb) +{ + struct skb_frag_struct *frag; + struct qdio_buffer *buffer; + int fragno, cnt, element; + unsigned long addr; + + QETH_DBF_TEXT(trace, 6, "tsfilfrg"); + + /*initialize variables ...*/ + fragno = skb_shinfo(skb)->nr_frags; + buffer = buf->buffer; + element = buf->next_element_to_fill; + /*fill buffer elements .....*/ + for (cnt = 0; cnt < fragno; cnt++) { + frag = &skb_shinfo(skb)->frags[cnt]; + addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + + frag->page_offset; + buffer->element[element].addr = (char *)addr; + buffer->element[element].length = frag->size; + if (cnt < (fragno - 1)) + buffer->element[element].flags = + SBAL_FLAGS_MIDDLE_FRAG; + else + buffer->element[element].flags = + SBAL_FLAGS_LAST_FRAG; + element++; + } + buf->next_element_to_fill = element; +} + +static inline int +qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf, + struct sk_buff *skb) +{ + int length, length_here, element; + int hdr_len; + struct qdio_buffer *buffer; + struct qeth_hdr_tso *hdr; + char *data; + + QETH_DBF_TEXT(trace, 3, "tsfilbuf"); + + /*increment user count and queue skb ...*/ + atomic_inc(&skb->users); + skb_queue_tail(&buf->skb_list, skb); + + /*initialize all variables...*/ + buffer = buf->buffer; + hdr = (struct qeth_hdr_tso *)skb->data; + hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len; + data = skb->data + hdr_len; + length = skb->len - hdr_len; + element = buf->next_element_to_fill; + /*fill first buffer entry only with header information */ + buffer->element[element].addr = skb->data; + buffer->element[element].length = hdr_len; + buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG; + buf->next_element_to_fill++; + + if (skb_shinfo(skb)->nr_frags > 0) { + __qeth_tso_fill_buffer_frag(buf, skb); + goto out; + } + + /*start filling buffer entries ...*/ + element++; + while (length > 0) { + /* length_here is the remaining amount of data in this page */ + length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE); + if (length < length_here) + length_here = length; + buffer->element[element].addr = data; + buffer->element[element].length = length_here; + length -= length_here; + if (!length) + buffer->element[element].flags = + SBAL_FLAGS_LAST_FRAG; + else + buffer->element[element].flags = + SBAL_FLAGS_MIDDLE_FRAG; + data += length_here; + element++; + } + /*set the buffer to primed ...*/ + buf->next_element_to_fill = element; +out: + atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); + return 1; +} + +int +qeth_tso_send_packet(struct qeth_card *card, struct sk_buff *skb, + struct qeth_qdio_out_q *queue, int ipv, int cast_type) +{ + int flush_cnt = 0; + struct qeth_hdr_tso *hdr; + struct qeth_qdio_out_buffer *buffer; + int start_index; + + QETH_DBF_TEXT(trace, 3, "tsosend"); + + if (!(hdr = qeth_tso_prepare_packet(card, skb, ipv, cast_type))) + return -ENOMEM; + /*check if skb fits in one SBAL ...*/ + if (!(qeth_get_elements_no(card, (void*)hdr, skb))) + return -EINVAL; + /*lock queue, force switching to non-packing and send it ...*/ + while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED, + QETH_OUT_Q_LOCKED, + &queue->state)); + start_index = queue->next_buf_to_fill; + buffer = &queue->bufs[queue->next_buf_to_fill]; + /*check if card is too busy ...*/ + if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){ + card->stats.tx_dropped++; + goto out; + } + /*let's force to non-packing and get a new SBAL*/ + flush_cnt += qeth_tso_get_queue_buffer(queue); + buffer = &queue->bufs[queue->next_buf_to_fill]; + if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { + card->stats.tx_dropped++; + goto out; + } + flush_cnt += qeth_tso_fill_buffer(buffer, skb); + queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % + QDIO_MAX_BUFFERS_PER_Q; +out: + atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); + if (flush_cnt) + qeth_flush_buffers(queue, 0, start_index, flush_cnt); + /*do some statistics */ + card->stats.tx_packets++; + card->stats.tx_bytes += skb->len; + return 0; +} diff --git a/trunk/drivers/s390/net/qeth_tso.h b/trunk/drivers/s390/net/qeth_tso.h index ad33e6f466f1..83504dee3f57 100644 --- a/trunk/drivers/s390/net/qeth_tso.h +++ b/trunk/drivers/s390/net/qeth_tso.h @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.7 $) + * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.4 $) * * Header file for qeth TCP Segmentation Offload support. * @@ -7,148 +7,52 @@ * * Author(s): Frank Pavlic * - * $Revision: 1.7 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.4 $ $Date: 2005/03/24 09:04:18 $ * */ #ifndef __QETH_TSO_H__ #define __QETH_TSO_H__ -#include -#include -#include -#include -#include -#include "qeth.h" -#include "qeth_mpc.h" +extern int +qeth_tso_send_packet(struct qeth_card *, struct sk_buff *, + struct qeth_qdio_out_q *, int , int); -static inline struct qeth_hdr_tso * -qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb) -{ - QETH_DBF_TEXT(trace, 5, "tsoprsk"); - return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_tso)); -} - -/** - * fill header for a TSO packet - */ -static inline void -qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb) -{ - struct qeth_hdr_tso *hdr; - struct tcphdr *tcph; - struct iphdr *iph; - - QETH_DBF_TEXT(trace, 5, "tsofhdr"); - - hdr = (struct qeth_hdr_tso *) skb->data; - iph = skb->nh.iph; - tcph = skb->h.th; - /*fix header to TSO values ...*/ - hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO; - /*set values which are fix for the first approach ...*/ - hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso); - hdr->ext.imb_hdr_no = 1; - hdr->ext.hdr_type = 1; - hdr->ext.hdr_version = 1; - hdr->ext.hdr_len = 28; - /*insert non-fix values */ - hdr->ext.mss = skb_shinfo(skb)->tso_size; - hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4); - hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len - - sizeof(struct qeth_hdr_tso)); -} - -/** - * change some header values as requested by hardware - */ -static inline void -qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipv6hdr *ip6h; - struct tcphdr *tcph; +struct qeth_hdr_ext_tso { + __u16 hdr_tot_len; + __u8 imb_hdr_no; + __u8 reserved; + __u8 hdr_type; + __u8 hdr_version; + __u16 hdr_len; + __u32 payload_len; + __u16 mss; + __u16 dg_hdr_len; + __u8 padding[16]; +} __attribute__ ((packed)); - iph = skb->nh.iph; - ip6h = skb->nh.ipv6h; - tcph = skb->h.th; +struct qeth_hdr_tso { + struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/ + struct qeth_hdr_ext_tso ext; +} __attribute__ ((packed)); - tcph->check = 0; - if (skb->protocol == ETH_P_IPV6) { - ip6h->payload_len = 0; - tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, - 0, IPPROTO_TCP, 0); - return; - } - /*OSA want us to set these values ...*/ - tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - 0, IPPROTO_TCP, 0); - iph->tot_len = 0; - iph->check = 0; -} +/*some helper functions*/ static inline int -qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb, - int ipv, int cast_type) -{ - struct qeth_hdr_tso *hdr; - - QETH_DBF_TEXT(trace, 5, "tsoprep"); - - hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb); - if (hdr == NULL) { - QETH_DBF_TEXT(trace, 4, "tsoperr"); - return -ENOMEM; - } - memset(hdr, 0, sizeof(struct qeth_hdr_tso)); - /*fill first 32 bytes of qdio header as used - *FIXME: TSO has two struct members - * with different names but same size - * */ - qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type); - qeth_tso_fill_header(card, skb); - qeth_tso_set_tcpip_header(card, skb); - return 0; -} - -static inline void -__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer, - int is_tso, int *next_element_to_fill) +qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) { - struct skb_frag_struct *frag; - int fragno; - unsigned long addr; - int element, cnt, dlen; - - fragno = skb_shinfo(skb)->nr_frags; - element = *next_element_to_fill; - dlen = 0; - - if (is_tso) - buffer->element[element].flags = - SBAL_FLAGS_MIDDLE_FRAG; - else - buffer->element[element].flags = - SBAL_FLAGS_FIRST_FRAG; - if ( (dlen = (skb->len - skb->data_len)) ) { - buffer->element[element].addr = skb->data; - buffer->element[element].length = dlen; - element++; - } - for (cnt = 0; cnt < fragno; cnt++) { - frag = &skb_shinfo(skb)->frags[cnt]; - addr = (page_to_pfn(frag->page) << PAGE_SHIFT) + - frag->page_offset; - buffer->element[element].addr = (char *)addr; - buffer->element[element].length = frag->size; - if (cnt < (fragno - 1)) - buffer->element[element].flags = - SBAL_FLAGS_MIDDLE_FRAG; - else - buffer->element[element].flags = - SBAL_FLAGS_LAST_FRAG; - element++; + int elements_needed = 0; + + if (skb_shinfo(skb)->nr_frags > 0) + elements_needed = (skb_shinfo(skb)->nr_frags + 1); + if (elements_needed == 0 ) + elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + + skb->len) >> PAGE_SHIFT); + if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ + PRINT_ERR("qeth_do_send_packet: invalid size of " + "IP packet. Discarded."); + return 0; } - *next_element_to_fill = element; + return elements_needed; } #endif /* __QETH_TSO_H__ */ diff --git a/trunk/net/sched/sch_netem.c b/trunk/net/sched/sch_netem.c index e0c9fbe73b15..5c0f0c209a4c 100644 --- a/trunk/net/sched/sch_netem.c +++ b/trunk/net/sched/sch_netem.c @@ -203,42 +203,47 @@ static int netem_run(struct Qdisc *sch) return 0; } +/* + * Insert one skb into qdisc. + * Note: parent depends on return value to account for queue length. + * NET_XMIT_DROP: queue length didn't change. + * NET_XMIT_SUCCESS: one skb was queued. + */ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct netem_sched_data *q = qdisc_priv(sch); + struct sk_buff *skb2; int ret; + int count = 1; pr_debug("netem_enqueue skb=%p\n", skb); + /* Random duplication */ + if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) + ++count; + /* Random packet drop 0 => none, ~0 => all */ - if (q->loss && q->loss >= get_crandom(&q->loss_cor)) { - pr_debug("netem_enqueue: random loss\n"); + if (q->loss && q->loss >= get_crandom(&q->loss_cor)) + --count; + + if (count == 0) { sch->qstats.drops++; kfree_skb(skb); - return 0; /* lie about loss so TCP doesn't know */ + return NET_XMIT_DROP; } - /* Random duplication */ - if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) { - struct sk_buff *skb2; - - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 && netem_delay(sch, skb2) == NET_XMIT_SUCCESS) { - struct Qdisc *qp; - - /* Since one packet can generate two packets in the - * queue, the parent's qlen accounting gets confused, - * so fix it. - */ - qp = qdisc_lookup(sch->dev, TC_H_MAJ(sch->parent)); - if (qp) - qp->q.qlen++; - - sch->q.qlen++; - sch->bstats.bytes += skb2->len; - sch->bstats.packets++; - } else - sch->qstats.drops++; + /* + * If we need to duplicate packet, then re-insert at top of the + * qdisc tree, since parent queuer expects that only one + * skb will be queued. + */ + if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { + struct Qdisc *rootq = sch->dev->qdisc; + u32 dupsave = q->duplicate; /* prevent duplicating a dup... */ + q->duplicate = 0; + + rootq->enqueue(skb2, rootq); + q->duplicate = dupsave; } /* If doing simple delay then gap == 0 so all packets