diff options
Diffstat (limited to 'drivers/s390/net')
-rw-r--r-- | drivers/s390/net/claw.c | 20 | ||||
-rw-r--r-- | drivers/s390/net/ctcmain.c | 41 | ||||
-rw-r--r-- | drivers/s390/net/fsm.c | 2 | ||||
-rw-r--r-- | drivers/s390/net/fsm.h | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth.h | 51 | ||||
-rw-r--r-- | drivers/s390/net/qeth_fs.h | 12 | ||||
-rw-r--r-- | drivers/s390/net/qeth_main.c | 615 | ||||
-rw-r--r-- | drivers/s390/net/qeth_mpc.c | 6 | ||||
-rw-r--r-- | drivers/s390/net/qeth_mpc.h | 15 | ||||
-rw-r--r-- | drivers/s390/net/qeth_proc.c | 126 | ||||
-rw-r--r-- | drivers/s390/net/qeth_sys.c | 41 |
11 files changed, 620 insertions, 311 deletions
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 24c0af49c25..3092473991a 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -2,9 +2,9 @@ * drivers/s390/net/claw.c * ESCON CLAW network driver * - * $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $ + * $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ * - * Linux fo zSeries version + * Linux for zSeries version * Copyright (C) 2002,2005 IBM Corporation * Author(s) Original code written by: * Kazuo Iimura (iimura@jp.ibm.com) @@ -431,12 +431,12 @@ claw_pack_skb(struct claw_privbk *privptr) if (!skb_queue_empty(&p_ch->collect_queue)) { /* some data */ held_skb = skb_dequeue(&p_ch->collect_queue); - if (p_env->packing != DO_PACKED) - return held_skb; if (held_skb) - atomic_dec(&held_skb->users); + dev_kfree_skb_any(held_skb); else return NULL; + if (p_env->packing != DO_PACKED) + return held_skb; /* get a new SKB we will pack at least one */ new_skb = dev_alloc_skb(p_env->write_size); if (new_skb == NULL) { @@ -455,7 +455,7 @@ claw_pack_skb(struct claw_privbk *privptr) privptr->stats.tx_packets++; so_far += held_skb->len; pkt_cnt++; - dev_kfree_skb_irq(held_skb); + dev_kfree_skb_any(held_skb); held_skb = skb_dequeue(&p_ch->collect_queue); if (held_skb) atomic_dec(&held_skb->users); @@ -1092,7 +1092,7 @@ claw_release(struct net_device *dev) } } if (privptr->pk_skb != NULL) { - dev_kfree_skb(privptr->pk_skb); + dev_kfree_skb_any(privptr->pk_skb); privptr->pk_skb = NULL; } if(privptr->buffs_alloc != 1) { @@ -2016,7 +2016,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) p_buf=(struct ccwbk*)privptr->p_end_ccw; dumpit((char *)p_buf, sizeof(struct endccw)); #endif - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); if (linkid==0) { lock=LOCK_NO; } @@ -4061,7 +4061,7 @@ claw_purge_skb_queue(struct sk_buff_head *q) while ((skb = skb_dequeue(q))) { atomic_dec(&skb->users); - dev_kfree_skb_irq(skb); + dev_kfree_skb_any(skb); } } @@ -4410,7 +4410,7 @@ claw_init(void) #else "compiled into kernel " #endif - " $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $ \n"); + " $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ \n"); #ifdef FUNCTRACE diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 96ca863eaff..0db4f57a6a9 100644 --- a/drivers/s390/net/ctcmain.c +++ b/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.78 2005/09/07 12:18:02 pavlic Exp $ * * CTC / ESCON network driver * @@ -37,10 +37,9 @@ * 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.78 $ * */ - #undef DEBUG #include <linux/module.h> #include <linux/init.h> @@ -135,7 +134,7 @@ static const char *dev_event_names[] = { "TX down", "Restart", }; - + /** * Events of the channel statemachine */ @@ -249,7 +248,7 @@ static void print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.74 $"; + char vbuf[] = "$Revision: 1.78 $"; char *version = vbuf; if (printed) @@ -334,7 +333,7 @@ static const char *ch_state_names[] = { "Restarting", "Not operational", }; - + #ifdef DEBUG /** * Dump header and first 16 bytes of an sk_buff for debugging purposes. @@ -671,7 +670,7 @@ static void fsm_action_nop(fsm_instance * fi, int event, void *arg) { } - + /** * Actions for channel - statemachines. *****************************************************************************/ @@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int event, void *arg) fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev); } - /** * The statemachine for a channel. */ @@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = { }; static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node); - + /** * Functions related to setup and device detection. *****************************************************************************/ @@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) fsm_event(ch->fsm, CH_EVENT_IRQ, ch); } - + /** * Actions for interface - statemachine. *****************************************************************************/ @@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) int rc = 0; DBF_TEXT(trace, 5, __FUNCTION__); + /* we need to acquire the lock for testing the state + * otherwise we can have an IRQ changing the state to + * TXIDLE after the test but before acquiring the lock. + */ + spin_lock_irqsave(&ch->collect_lock, saveflags); if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) { int l = skb->len + LL_HEADER_LENGTH; - spin_lock_irqsave(&ch->collect_lock, saveflags); - if (ch->collect_len + l > ch->max_bufsize - 2) - rc = -EBUSY; - else { + if (ch->collect_len + l > ch->max_bufsize - 2) { + spin_unlock_irqrestore(&ch->collect_lock, saveflags); + return -EBUSY; + } else { atomic_inc(&skb->users); header.length = l; header.type = skb->protocol; @@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) int ccw_idx; struct sk_buff *nskb; unsigned long hi; - + spin_unlock_irqrestore(&ch->collect_lock, saveflags); /** * Protect skb against beeing free'd by upper * layers. @@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) if (!nskb) { atomic_dec(&skb->users); skb_pull(skb, LL_HEADER_LENGTH + 2); + ctc_clear_busy(ch->netdev); return -ENOMEM; } else { memcpy(skb_put(nskb, skb->len), @@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) */ atomic_dec(&skb->users); skb_pull(skb, LL_HEADER_LENGTH + 2); + ctc_clear_busy(ch->netdev); return -EBUSY; } @@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) } } + ctc_clear_busy(ch->netdev); return rc; } - + /** * Interface API for upper network layers *****************************************************************************/ @@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev) dev->trans_start = jiffies; if (transmit_skb(privptr->channel[WRITE], skb) != 0) rc = 1; - ctc_clear_busy(dev); return rc; } @@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct device_attribute *attr, const char *buf, return count; } - static void ctc_netdev_unregister(struct net_device * dev) { @@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b return count; } - static ssize_t ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c index fa09440d82e..38f50b7129a 100644 --- a/drivers/s390/net/fsm.c +++ b/drivers/s390/net/fsm.c @@ -16,7 +16,7 @@ MODULE_LICENSE("GPL"); fsm_instance * init_fsm(char *name, const char **state_names, const char **event_names, int nr_states, - int nr_events, const fsm_node *tmpl, int tmpl_len, int order) + int nr_events, const fsm_node *tmpl, int tmpl_len, gfp_t order) { int i; fsm_instance *this; diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h index f9a011001eb..1b8a7e7c34f 100644 --- a/drivers/s390/net/fsm.h +++ b/drivers/s390/net/fsm.h @@ -110,7 +110,7 @@ extern fsm_instance * init_fsm(char *name, const char **state_names, const char **event_names, int nr_states, int nr_events, const fsm_node *tmpl, - int tmpl_len, int order); + int tmpl_len, gfp_t order); /** * Releases an FSM diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 3a0285669ad..38a2441564d 100644 --- a/drivers/s390/net/qeth.h +++ b/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.142 $" #ifdef CONFIG_QETH_IPV6 #define QETH_VERSION_IPV6 ":IPv6" @@ -275,6 +275,10 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func) QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \ QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \ QETH_MAX_QUEUES,0x103}, \ + {0x1731,0x06,0x1732,0x06,QETH_CARD_TYPE_OSN,0, \ + QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \ + QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \ + QETH_MAX_QUEUES,0}, \ {0,0,0,0,0,0,0,0,0}} #define QETH_REAL_CARD 1 @@ -363,10 +367,22 @@ struct qeth_hdr_layer2 { __u8 reserved2[16]; } __attribute__ ((packed)); +struct qeth_hdr_osn { + __u8 id; + __u8 reserved; + __u16 seq_no; + __u16 reserved2; + __u16 control_flags; + __u16 pdu_length; + __u8 reserved3[18]; + __u32 ccid; +} __attribute__ ((packed)); + struct qeth_hdr { union { struct qeth_hdr_layer2 l2; struct qeth_hdr_layer3 l3; + struct qeth_hdr_osn osn; } hdr; } __attribute__ ((packed)); @@ -413,6 +429,7 @@ enum qeth_header_ids { QETH_HEADER_TYPE_LAYER3 = 0x01, QETH_HEADER_TYPE_LAYER2 = 0x02, QETH_HEADER_TYPE_TSO = 0x03, + QETH_HEADER_TYPE_OSN = 0x04, }; /* flags for qeth_hdr.ext_flags */ #define QETH_HDR_EXT_VLAN_FRAME 0x01 @@ -582,7 +599,6 @@ enum qeth_card_states { * Protocol versions */ enum qeth_prot_versions { - QETH_PROT_SNA = 0x0001, QETH_PROT_IPV4 = 0x0004, QETH_PROT_IPV6 = 0x0006, }; @@ -686,6 +702,7 @@ struct qeth_seqno { __u32 pdu_hdr; __u32 pdu_hdr_ack; __u16 ipa; + __u32 pkt_seqno; }; struct qeth_reply { @@ -760,6 +777,11 @@ enum qeth_threads { QETH_RECOVER_THREAD = 2, }; +struct qeth_osn_info { + int (*assist_cb)(struct net_device *dev, void *data); + int (*data_cb)(struct sk_buff *skb); +}; + struct qeth_card { struct list_head list; enum qeth_card_states state; @@ -802,6 +824,7 @@ struct qeth_card { int use_hard_stop; int (*orig_hard_header)(struct sk_buff *,struct net_device *, unsigned short,void *,void *,unsigned); + struct qeth_osn_info osn_info; }; struct qeth_card_list_struct { @@ -848,6 +871,7 @@ qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size) "on interface %s", QETH_CARD_IFNAME(card)); return -ENOMEM; } + kfree_skb(*skb); *skb = new_skb; } return 0; @@ -914,10 +938,12 @@ qeth_get_hlen(__u8 link_type) static inline unsigned short qeth_get_netdev_flags(struct qeth_card *card) { - if (card->options.layer2) + if (card->options.layer2 && + (card->info.type == QETH_CARD_TYPE_OSAE)) return 0; switch (card->info.type) { case QETH_CARD_TYPE_IQD: + case QETH_CARD_TYPE_OSN: return IFF_NOARP; #ifdef CONFIG_QETH_IPV6 default: @@ -954,9 +980,10 @@ static inline int qeth_get_max_mtu_for_card(int cardtype) { switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: - return 61440; case QETH_CARD_TYPE_OSAE: + case QETH_CARD_TYPE_OSN: return 61440; case QETH_CARD_TYPE_IQD: return 57344; @@ -1002,6 +1029,7 @@ qeth_mtu_is_valid(struct qeth_card * card, int mtu) case QETH_CARD_TYPE_IQD: return ((mtu >= 576) && (mtu <= card->info.max_mtu + 4096 - 32)); + case QETH_CARD_TYPE_OSN: case QETH_CARD_TYPE_UNKNOWN: default: return 1; @@ -1013,6 +1041,7 @@ qeth_get_arphdr_type(int cardtype, int linktype) { switch (cardtype) { case QETH_CARD_TYPE_OSAE: + case QETH_CARD_TYPE_OSN: switch (linktype) { case QETH_LINK_TYPE_LANE_TR: case QETH_LINK_TYPE_HSTR: @@ -1172,7 +1201,7 @@ extern int qeth_realloc_buffer_pool(struct qeth_card *, int); extern int -qeth_set_large_send(struct qeth_card *); +qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types); extern void qeth_fill_header(struct qeth_card *, struct qeth_hdr *, @@ -1180,4 +1209,16 @@ qeth_fill_header(struct qeth_card *, struct qeth_hdr *, extern void qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int); +extern int +qeth_osn_assist(struct net_device *, void *, int); + +extern int +qeth_osn_register(unsigned char *read_dev_no, + struct net_device **, + int (*assist_cb)(struct net_device *, void *), + int (*data_cb)(struct sk_buff *)); + +extern void +qeth_osn_deregister(struct net_device *); + #endif /* __QETH_H__ */ diff --git a/drivers/s390/net/qeth_fs.h b/drivers/s390/net/qeth_fs.h index 5c9a51ce91b..c0b4c8d82c4 100644 --- a/drivers/s390/net/qeth_fs.h +++ b/drivers/s390/net/qeth_fs.h @@ -12,7 +12,7 @@ #ifndef __QETH_FS_H__ #define __QETH_FS_H__ -#define VERSION_QETH_FS_H "$Revision: 1.9 $" +#define VERSION_QETH_FS_H "$Revision: 1.10 $" extern const char *VERSION_QETH_PROC_C; extern const char *VERSION_QETH_SYS_C; @@ -43,6 +43,12 @@ extern void qeth_remove_device_attributes(struct device *dev); extern int +qeth_create_device_attributes_osn(struct device *dev); + +extern void +qeth_remove_device_attributes_osn(struct device *dev); + +extern int qeth_create_driver_attributes(void); extern void @@ -108,6 +114,8 @@ qeth_get_cardname(struct qeth_card *card) return " OSD Express"; case QETH_CARD_TYPE_IQD: return " HiperSockets"; + case QETH_CARD_TYPE_OSN: + return " OSN QDIO"; default: return " unknown"; } @@ -153,6 +161,8 @@ qeth_get_cardname_short(struct qeth_card *card) } case QETH_CARD_TYPE_IQD: return "HiperSockets"; + case QETH_CARD_TYPE_OSN: + return "OSN"; default: return "unknown"; } diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 8f4d2999af8..692003c9f89 100644 --- a/drivers/s390/net/qeth_main.c +++ b/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.224 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -12,7 +12,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Thomas Spatzier <tspat@de.ibm.com> * - * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $ + * $Revision: 1.224 $ $Date: 2005/05/04 20:19: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 @@ -29,14 +29,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/*** - * eye catcher; just for debugging purposes - */ -void volatile -qeth_eyecatcher(void) -{ - return; -} #include <linux/config.h> #include <linux/module.h> @@ -80,7 +72,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.224 $" static const char *version = "qeth S/390 OSA-Express driver"; /** @@ -204,7 +196,6 @@ qeth_notifier_register(struct task_struct *p, int signum) { struct qeth_notify_list_struct *n_entry; - /*check first if entry already exists*/ spin_lock(&qeth_notify_lock); list_for_each_entry(n_entry, &qeth_notify_list, list) { @@ -519,7 +510,7 @@ static int __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) { struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data; - int rc = 0; + int rc = 0, rc2 = 0, rc3 = 0; enum qeth_card_states recover_flag; QETH_DBF_TEXT(setup, 3, "setoffl"); @@ -531,11 +522,13 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) CARD_BUS_ID(card)); return -ERESTARTSYS; } - if ((rc = ccw_device_set_offline(CARD_DDEV(card))) || - (rc = ccw_device_set_offline(CARD_WDEV(card))) || - (rc = ccw_device_set_offline(CARD_RDEV(card)))) { + rc = ccw_device_set_offline(CARD_DDEV(card)); + rc2 = ccw_device_set_offline(CARD_WDEV(card)); + rc3 = ccw_device_set_offline(CARD_RDEV(card)); + if (!rc) + rc = (rc2) ? rc2 : rc3; + if (rc) QETH_DBF_TEXT_(setup, 2, "1err%d", rc); - } if (recover_flag == CARD_STATE_UP) card->state = CARD_STATE_RECOVER; qeth_notify_processes(); @@ -1030,7 +1023,10 @@ qeth_set_intial_options(struct qeth_card *card) card->options.fake_broadcast = 0; card->options.add_hhlen = DEFAULT_ADD_HHLEN; card->options.fake_ll = 0; - card->options.layer2 = 0; + if (card->info.type == QETH_CARD_TYPE_OSN) + card->options.layer2 = 1; + else + card->options.layer2 = 0; } /** @@ -1054,6 +1050,7 @@ qeth_setup_card(struct qeth_card *card) spin_lock_init(&card->vlanlock); card->vlangrp = NULL; #endif + spin_lock_init(&card->lock); spin_lock_init(&card->ip_lock); spin_lock_init(&card->thread_mask_lock); card->thread_start_mask = 0; @@ -1118,19 +1115,20 @@ qeth_determine_card_type(struct qeth_card *card) QETH_DBF_TEXT(setup, 2, "detcdtyp"); + card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; + card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; while (known_devices[i][4]) { if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) && (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) { card->info.type = known_devices[i][4]; + card->qdio.no_out_queues = known_devices[i][8]; + card->info.is_multicast_different = known_devices[i][9]; if (is_1920_device(card)) { PRINT_INFO("Priority Queueing not able " "due to hardware limitations!\n"); card->qdio.no_out_queues = 1; card->qdio.default_out_queue = 0; - } else { - card->qdio.no_out_queues = known_devices[i][8]; - } - card->info.is_multicast_different = known_devices[i][9]; + } return 0; } i++; @@ -1154,6 +1152,8 @@ qeth_probe_device(struct ccwgroup_device *gdev) if (!get_device(dev)) return -ENODEV; + QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id); + card = qeth_alloc_card(); if (!card) { put_device(dev); @@ -1163,28 +1163,27 @@ qeth_probe_device(struct ccwgroup_device *gdev) card->read.ccwdev = gdev->cdev[0]; card->write.ccwdev = gdev->cdev[1]; card->data.ccwdev = gdev->cdev[2]; - - if ((rc = qeth_setup_card(card))){ - QETH_DBF_TEXT_(setup, 2, "2err%d", rc); - put_device(dev); - qeth_free_card(card); - return rc; - } gdev->dev.driver_data = card; card->gdev = gdev; gdev->cdev[0]->handler = qeth_irq; gdev->cdev[1]->handler = qeth_irq; gdev->cdev[2]->handler = qeth_irq; - rc = qeth_create_device_attributes(dev); - if (rc) { + if ((rc = qeth_determine_card_type(card))){ + PRINT_WARN("%s: not a valid card type\n", __func__); + QETH_DBF_TEXT_(setup, 2, "3err%d", rc); + put_device(dev); + qeth_free_card(card); + return rc; + } + if ((rc = qeth_setup_card(card))){ + QETH_DBF_TEXT_(setup, 2, "2err%d", rc); put_device(dev); qeth_free_card(card); return rc; } - if ((rc = qeth_determine_card_type(card))){ - PRINT_WARN("%s: not a valid card type\n", __func__); - QETH_DBF_TEXT_(setup, 2, "3err%d", rc); + rc = qeth_create_device_attributes(dev); + if (rc) { put_device(dev); qeth_free_card(card); return rc; @@ -1634,16 +1633,6 @@ qeth_cmd_timeout(unsigned long data) spin_unlock_irqrestore(&reply->card->lock, flags); } -static void -qeth_reset_ip_addresses(struct qeth_card *card) -{ - QETH_DBF_TEXT(trace, 2, "rstipadd"); - - qeth_clear_ip_list(card, 0, 1); - /* this function will also schedule the SET_IP_THREAD */ - qeth_set_multicast_list(card->dev); -} - static struct qeth_ipa_cmd * qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) { @@ -1672,10 +1661,11 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) "IP address reset.\n", QETH_CARD_IFNAME(card), card->info.chpid); - card->lan_online = 1; netif_carrier_on(card->dev); - qeth_reset_ip_addresses(card); + qeth_schedule_recovery(card); return NULL; + case IPA_CMD_MODCCID: + return cmd; case IPA_CMD_REGISTER_LOCAL_ADDR: QETH_DBF_TEXT(trace,3, "irla"); break; @@ -1737,6 +1727,14 @@ qeth_send_control_data_cb(struct qeth_channel *channel, cmd = qeth_check_ipa_data(card, iob); if ((cmd == NULL) && (card->state != CARD_STATE_DOWN)) goto out; + /*in case of OSN : check if cmd is set */ + if (card->info.type == QETH_CARD_TYPE_OSN && + cmd && + cmd->hdr.command != IPA_CMD_STARTLAN && + card->osn_info.assist_cb != NULL) { + card->osn_info.assist_cb(card->dev, cmd); + goto out; + } spin_lock_irqsave(&card->lock, flags); list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) { @@ -1753,8 +1751,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel, keep_reply = reply->callback(card, reply, (unsigned long)cmd); - } - else + } else keep_reply = reply->callback(card, reply, (unsigned long)iob); @@ -1784,6 +1781,24 @@ out: qeth_release_buffer(channel,iob); } +static inline void +qeth_prepare_control_data(struct qeth_card *card, int len, +struct qeth_cmd_buffer *iob) +{ + qeth_setup_ccw(&card->write,iob->data,len); + iob->callback = qeth_release_buffer; + + memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data), + &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH); + card->seqno.trans_hdr++; + memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data), + &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH); + card->seqno.pdu_hdr++; + memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data), + &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH); + QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN); +} + static int qeth_send_control_data(struct qeth_card *card, int len, struct qeth_cmd_buffer *iob, @@ -1794,24 +1809,11 @@ qeth_send_control_data(struct qeth_card *card, int len, { int rc; unsigned long flags; - struct qeth_reply *reply; + struct qeth_reply *reply = NULL; struct timer_list timer; QETH_DBF_TEXT(trace, 2, "sendctl"); - qeth_setup_ccw(&card->write,iob->data,len); - - memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data), - &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH); - card->seqno.trans_hdr++; - - memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data), - &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH); - card->seqno.pdu_hdr++; - memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data), - &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH); - iob->callback = qeth_release_buffer; - reply = qeth_alloc_reply(card); if (!reply) { PRINT_WARN("Could no alloc qeth_reply!\n"); @@ -1826,10 +1828,6 @@ qeth_send_control_data(struct qeth_card *card, int len, init_timer(&timer); timer.function = qeth_cmd_timeout; timer.data = (unsigned long) reply; - if (IS_IPA(iob->data)) - timer.expires = jiffies + QETH_IPA_TIMEOUT; - else - timer.expires = jiffies + QETH_TIMEOUT; init_waitqueue_head(&reply->wait_q); spin_lock_irqsave(&card->lock, flags); list_add_tail(&reply->list, &card->cmd_waiter_list); @@ -1837,6 +1835,11 @@ qeth_send_control_data(struct qeth_card *card, int len, QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN); wait_event(card->wait_q, atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0); + qeth_prepare_control_data(card, len, iob); + if (IS_IPA(iob->data)) + timer.expires = jiffies + QETH_IPA_TIMEOUT; + else + timer.expires = jiffies + QETH_TIMEOUT; QETH_DBF_TEXT(trace, 6, "noirqpnd"); spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); rc = ccw_device_start(card->write.ccwdev, &card->write.ccw, @@ -1864,6 +1867,62 @@ qeth_send_control_data(struct qeth_card *card, int len, } static int +qeth_osn_send_control_data(struct qeth_card *card, int len, + struct qeth_cmd_buffer *iob) +{ + unsigned long flags; + int rc = 0; + + QETH_DBF_TEXT(trace, 5, "osndctrd"); + + wait_event(card->wait_q, + atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0); + qeth_prepare_control_data(card, len, iob); + QETH_DBF_TEXT(trace, 6, "osnoirqp"); + spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); + rc = ccw_device_start(card->write.ccwdev, &card->write.ccw, + (addr_t) iob, 0, 0); + spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags); + if (rc){ + PRINT_WARN("qeth_osn_send_control_data: " + "ccw_device_start rc = %i\n", rc); + QETH_DBF_TEXT_(trace, 2, " err%d", rc); + qeth_release_buffer(iob->channel, iob); + atomic_set(&card->write.irq_pending, 0); + wake_up(&card->wait_q); + } + return rc; +} + +static inline void +qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, + char prot_type) +{ + memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE); + memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1); + memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data), + &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH); +} + +static int +qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, + int data_len) +{ + u16 s1, s2; + +QETH_DBF_TEXT(trace,4,"osndipa"); + + qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2); + s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len); + s2 = (u16)data_len; + memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2); + memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2); + memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2); + memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2); + return qeth_osn_send_control_data(card, s1, iob); +} + +static int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, int (*reply_cb) (struct qeth_card *,struct qeth_reply*, unsigned long), @@ -1874,17 +1933,14 @@ qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, QETH_DBF_TEXT(trace,4,"sendipa"); - memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE); - if (card->options.layer2) - prot_type = QETH_PROT_LAYER2; + if (card->info.type == QETH_CARD_TYPE_OSN) + prot_type = QETH_PROT_OSN2; + else + prot_type = QETH_PROT_LAYER2; else prot_type = QETH_PROT_TCPIP; - - memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1); - memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data), - &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH); - + qeth_prepare_ipa_cmd(card,iob,prot_type); rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob, reply_cb, reply_param); return rc; @@ -2026,7 +2082,10 @@ qeth_ulp_enable(struct qeth_card *card) *(QETH_ULP_ENABLE_LINKNUM(iob->data)) = (__u8) card->info.portno; if (card->options.layer2) - prot_type = QETH_PROT_LAYER2; + if (card->info.type == QETH_CARD_TYPE_OSN) + prot_type = QETH_PROT_OSN2; + else + prot_type = QETH_PROT_LAYER2; else prot_type = QETH_PROT_TCPIP; @@ -2116,15 +2175,21 @@ qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf, } static inline struct sk_buff * -qeth_get_skb(unsigned int length) +qeth_get_skb(unsigned int length, struct qeth_hdr *hdr) { struct sk_buff* skb; + int add_len; + + add_len = 0; + if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN) + add_len = sizeof(struct qeth_hdr); #ifdef CONFIG_QETH_VLAN - if ((skb = dev_alloc_skb(length + VLAN_HLEN))) - skb_reserve(skb, VLAN_HLEN); -#else - skb = dev_alloc_skb(length); + else + add_len = VLAN_HLEN; #endif + skb = dev_alloc_skb(length + add_len); + if (skb && add_len) + skb_reserve(skb, add_len); return skb; } @@ -2154,7 +2219,10 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, offset += sizeof(struct qeth_hdr); if (card->options.layer2) - skb_len = (*hdr)->hdr.l2.pkt_length; + if (card->info.type == QETH_CARD_TYPE_OSN) + skb_len = (*hdr)->hdr.osn.pdu_length; + else + skb_len = (*hdr)->hdr.l2.pkt_length; else skb_len = (*hdr)->hdr.l3.length; @@ -2162,15 +2230,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, 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))) + if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr))) goto no_mem; skb_reserve(skb,QETH_FAKE_LL_LEN_TR); } else { - if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH))) + if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr))) goto no_mem; skb_reserve(skb,QETH_FAKE_LL_LEN_ETH); } - } else if (!(skb = qeth_get_skb(skb_len))) + } else if (!(skb = qeth_get_skb(skb_len, *hdr))) goto no_mem; data_ptr = element->addr + offset; while (skb_len) { @@ -2395,6 +2463,7 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, skb_pull(skb, VLAN_HLEN); } #endif + *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; return vlan_id; } @@ -2468,8 +2537,12 @@ qeth_process_inbound_buffer(struct qeth_card *card, skb->dev = card->dev; if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); - else + else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) qeth_rebuild_skb(card, skb, hdr); + else { /*in case of OSN*/ + skb_push(skb, sizeof(struct qeth_hdr)); + memcpy(skb->data, hdr, sizeof(struct qeth_hdr)); + } /* is device UP ? */ if (!(card->dev->flags & IFF_UP)){ dev_kfree_skb_any(skb); @@ -2480,7 +2553,10 @@ qeth_process_inbound_buffer(struct qeth_card *card, vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); else #endif - rxrc = netif_rx(skb); + if (card->info.type == QETH_CARD_TYPE_OSN) + rxrc = card->osn_info.data_cb(skb); + else + rxrc = netif_rx(skb); card->dev->last_rx = jiffies; card->stats.rx_packets++; card->stats.rx_bytes += skb->len; @@ -2759,11 +2835,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, queue->card->perf_stats.outbound_do_qdio_start_time; #endif if (rc){ - QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO " - "returned error (%i) on device %s.", - rc, CARD_DDEV_ID(queue->card)); QETH_DBF_TEXT(trace, 2, "flushbuf"); QETH_DBF_TEXT_(trace, 2, " err%d", rc); + QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card)); queue->card->stats.tx_errors += count; /* this must not happen under normal circumstances. if it * happens something is really wrong -> recover */ @@ -2909,11 +2983,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, QETH_DBF_TEXT(trace, 6, "qdouhdl"); if (status & QDIO_STATUS_LOOK_FOR_ERROR) { if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ - QETH_DBF_SPRINTF(trace, 2, "On device %s: " - "received active check " - "condition (0x%08x).", - CARD_BUS_ID(card), status); - QETH_DBF_TEXT(trace, 2, "chkcond"); + QETH_DBF_TEXT(trace, 2, "achkcond"); + QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card)); QETH_DBF_TEXT_(trace, 2, "%08x", status); netif_stop_queue(card->dev); qeth_schedule_recovery(card); @@ -3027,7 +3098,7 @@ qeth_alloc_buffer_pool(struct qeth_card *card) return -ENOMEM; } for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){ - ptr = (void *) __get_free_page(GFP_KERNEL); + ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA); if (!ptr) { while (j > 0) free_page((unsigned long) @@ -3071,7 +3142,8 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) if (card->qdio.state == QETH_QDIO_ALLOCATED) return 0; - card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), GFP_KERNEL); + card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), + GFP_KERNEL|GFP_DMA); if (!card->qdio.in_q) return - ENOMEM; QETH_DBF_TEXT(setup, 2, "inq"); @@ -3096,7 +3168,7 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) } for (i = 0; i < card->qdio.no_out_queues; ++i){ card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), - GFP_KERNEL); + GFP_KERNEL|GFP_DMA); if (!card->qdio.out_qs[i]){ while (i > 0) kfree(card->qdio.out_qs[--i]); @@ -3169,8 +3241,6 @@ qeth_init_qdio_info(struct qeth_card *card) INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list); INIT_LIST_HEAD(&card->qdio.init_pool.entry_list); /* outbound */ - card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; - card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; } static int @@ -3356,26 +3426,32 @@ qeth_halt_channel(struct qeth_channel *channel) static int qeth_halt_channels(struct qeth_card *card) { - int rc = 0; + int rc1 = 0, rc2=0, rc3 = 0; QETH_DBF_TEXT(trace,3,"haltchs"); - if ((rc = qeth_halt_channel(&card->read))) - return rc; - if ((rc = qeth_halt_channel(&card->write))) - return rc; - return qeth_halt_channel(&card->data); + rc1 = qeth_halt_channel(&card->read); + rc2 = qeth_halt_channel(&card->write); + rc3 = qeth_halt_channel(&card->data); + if (rc1) + return rc1; + if (rc2) + return rc2; + return rc3; } static int qeth_clear_channels(struct qeth_card *card) { - int rc = 0; + int rc1 = 0, rc2=0, rc3 = 0; QETH_DBF_TEXT(trace,3,"clearchs"); - if ((rc = qeth_clear_channel(&card->read))) - return rc; - if ((rc = qeth_clear_channel(&card->write))) - return rc; - return qeth_clear_channel(&card->data); + rc1 = qeth_clear_channel(&card->read); + rc2 = qeth_clear_channel(&card->write); + rc3 = qeth_clear_channel(&card->data); + if (rc1) + return rc1; + if (rc2) + return rc2; + return rc3; } static int @@ -3445,23 +3521,23 @@ qeth_mpc_initialize(struct qeth_card *card) } if ((rc = qeth_cm_enable(card))){ QETH_DBF_TEXT_(setup, 2, "2err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_cm_setup(card))){ QETH_DBF_TEXT_(setup, 2, "3err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_ulp_enable(card))){ QETH_DBF_TEXT_(setup, 2, "4err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_ulp_setup(card))){ QETH_DBF_TEXT_(setup, 2, "5err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_alloc_qdio_buffers(card))){ QETH_DBF_TEXT_(setup, 2, "5err%d", rc); - return rc; + goto out_qdio; } if ((rc = qeth_qdio_establish(card))){ QETH_DBF_TEXT_(setup, 2, "6err%d", rc); @@ -3479,7 +3555,7 @@ qeth_mpc_initialize(struct qeth_card *card) return 0; out_qdio: - qeth_qdio_clear_card(card, card->info.type==QETH_CARD_TYPE_OSAE); + qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD); return rc; } @@ -3504,6 +3580,9 @@ qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype) case QETH_CARD_TYPE_IQD: dev = alloc_netdev(0, "hsi%d", ether_setup); break; + case QETH_CARD_TYPE_OSN: + dev = alloc_netdev(0, "osn%d", ether_setup); + break; default: dev = alloc_etherdev(0); } @@ -3668,7 +3747,8 @@ qeth_open(struct net_device *dev) if (card->state != CARD_STATE_SOFTSETUP) return -ENODEV; - if ( (card->options.layer2) && + if ( (card->info.type != QETH_CARD_TYPE_OSN) && + (card->options.layer2) && (!card->info.layer2_mac_registered)) { QETH_DBF_TEXT(trace,4,"nomacadr"); return -EPERM; @@ -3706,6 +3786,9 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) { int cast_type = RTN_UNSPEC; + if (card->info.type == QETH_CARD_TYPE_OSN) + return cast_type; + if (skb->dst && skb->dst->neighbour){ cast_type = skb->dst->neighbour->type; if ((cast_type == RTN_BROADCAST) || @@ -3795,12 +3878,19 @@ 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"); - + if (card->info.type == QETH_CARD_TYPE_OSN) { + *hdr = (struct qeth_hdr *)(*skb)->data; + return rc; + } + 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) ) { @@ -4251,7 +4341,8 @@ out: } static inline int -qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) +qeth_get_elements_no(struct qeth_card *card, void *hdr, + struct sk_buff *skb, int elems) { int elements_needed = 0; @@ -4261,9 +4352,10 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) if (elements_needed == 0 ) elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + skb->len) >> PAGE_SHIFT); - if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ + if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ PRINT_ERR("qeth_do_send_packet: invalid size of " - "IP packet. Discarded."); + "IP packet (Number=%d / Length=%d). Discarded.\n", + (elements_needed+elems), skb->len); return 0; } return elements_needed; @@ -4275,7 +4367,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) int ipv = 0; int cast_type; struct qeth_qdio_out_q *queue; - struct qeth_hdr *hdr; + struct qeth_hdr *hdr = NULL; int elements_needed = 0; enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; struct qeth_eddp_context *ctx = NULL; @@ -4298,8 +4390,14 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) } } } + if ((card->info.type == QETH_CARD_TYPE_OSN) && + (skb->protocol == htons(ETH_P_IPV6))) { + dev_kfree_skb_any(skb); + return 0; + } cast_type = qeth_get_cast_type(card, skb); - if ((cast_type == RTN_BROADCAST) && (card->info.broadcast_capable == 0)){ + if ((cast_type == RTN_BROADCAST) && + (card->info.broadcast_capable == 0)){ card->stats.tx_dropped++; card->stats.tx_errors++; dev_kfree_skb_any(skb); @@ -4327,7 +4425,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); return rc; } - qeth_fill_header(card, hdr, skb, ipv, cast_type); + if (card->info.type != QETH_CARD_TYPE_OSN) + qeth_fill_header(card, hdr, skb, ipv, cast_type); } if (large_send == QETH_LARGE_SEND_EDDP) { @@ -4337,9 +4436,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) return -EINVAL; } } else { - elements_needed += qeth_get_elements_no(card,(void*) hdr, skb); - if (!elements_needed) + int elems = qeth_get_elements_no(card,(void*) hdr, skb, + elements_needed); + if (!elems) return -EINVAL; + elements_needed += elems; } if (card->info.type != QETH_CARD_TYPE_IQD) @@ -4386,6 +4487,7 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum) case MII_BMCR: /* Basic mode control register */ rc = BMCR_FULLDPLX; if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&& + (card->info.link_type != QETH_LINK_TYPE_OSN) && (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH)) rc |= BMCR_SPEED100; break; @@ -4504,7 +4606,11 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries) QETH_DBF_TEXT(trace,3,"arpstnoe"); - /* TODO: really not supported by GuestLAN? */ + /* + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES; + * thus we say EOPNOTSUPP for this ARP function + */ if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { @@ -4681,14 +4787,6 @@ qeth_arp_query(struct qeth_card *card, char *udata) QETH_DBF_TEXT(trace,3,"arpquery"); - /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions - */ - /*if (card->info.guestlan) - return -EOPNOTSUPP; */ if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ IPA_ARP_PROCESSING)) { PRINT_WARN("ARP processing not supported " @@ -4894,10 +4992,9 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry) QETH_DBF_TEXT(trace,3,"arpadent"); /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY; + * thus we say EOPNOTSUPP for this ARP function */ if (card->info.guestlan) return -EOPNOTSUPP; @@ -4937,10 +5034,9 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry QETH_DBF_TEXT(trace,3,"arprment"); /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY; + * thus we say EOPNOTSUPP for this ARP function */ if (card->info.guestlan) return -EOPNOTSUPP; @@ -4978,11 +5074,10 @@ qeth_arp_flush_cache(struct qeth_card *card) QETH_DBF_TEXT(trace,3,"arpflush"); /* - * currently GuestLAN does only deliver all zeros on query arp, - * even though arp processing is supported (according to IPA supp. - * funcs flags); since all zeros is no valueable information, - * we say EOPNOTSUPP for all ARP functions - */ + * currently GuestLAN only supports the ARP assist function + * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE; + * thus we say EOPNOTSUPP for this ARP function + */ if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) return -EOPNOTSUPP; if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { @@ -5016,6 +5111,9 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) (card->state != CARD_STATE_SOFTSETUP)) return -ENODEV; + if (card->info.type == QETH_CARD_TYPE_OSN) + return -EPERM; + switch (cmd){ case SIOC_QETH_ARP_SET_NO_ENTRIES: if ( !capable(CAP_NET_ADMIN) || @@ -5206,7 +5304,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) if (!card->vlangrp) return; rcu_read_lock(); - in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]); + in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); if (!in_dev) goto out; for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { @@ -5341,6 +5439,9 @@ qeth_set_multicast_list(struct net_device *dev) { struct qeth_card *card = (struct qeth_card *) dev->priv; + if (card->info.type == QETH_CARD_TYPE_OSN) + return ; + QETH_DBF_TEXT(trace,3,"setmulti"); qeth_delete_mc_addresses(card); qeth_add_multicast_ipv4(card); @@ -5382,6 +5483,94 @@ qeth_get_addr_buffer(enum qeth_prot_versions prot) return addr; } +int +qeth_osn_assist(struct net_device *dev, + void *data, + int data_len) +{ + struct qeth_cmd_buffer *iob; + struct qeth_card *card; + int rc; + + QETH_DBF_TEXT(trace, 2, "osnsdmc"); + if (!dev) + return -ENODEV; + card = (struct qeth_card *)dev->priv; + if (!card) + return -ENODEV; + if ((card->state != CARD_STATE_UP) && + (card->state != CARD_STATE_SOFTSETUP)) + return -ENODEV; + iob = qeth_wait_for_buffer(&card->write); + memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len); + rc = qeth_osn_send_ipa_cmd(card, iob, data_len); + return rc; +} + +static struct net_device * +qeth_netdev_by_devno(unsigned char *read_dev_no) +{ + struct qeth_card *card; + struct net_device *ndev; + unsigned char *readno; + __u16 temp_dev_no, card_dev_no; + char *endp; + unsigned long flags; + + ndev = NULL; + memcpy(&temp_dev_no, read_dev_no, 2); + read_lock_irqsave(&qeth_card_list.rwlock, flags); + list_for_each_entry(card, &qeth_card_list.list, list) { + readno = CARD_RDEV_ID(card); + readno += (strlen(readno) - 4); + card_dev_no = simple_strtoul(readno, &endp, 16); + if (card_dev_no == temp_dev_no) { + ndev = card->dev; + break; + } + } + read_unlock_irqrestore(&qeth_card_list.rwlock, flags); + return ndev; +} + +int +qeth_osn_register(unsigned char *read_dev_no, + struct net_device **dev, + int (*assist_cb)(struct net_device *, void *), + int (*data_cb)(struct sk_buff *)) +{ + struct qeth_card * card; + + QETH_DBF_TEXT(trace, 2, "osnreg"); + *dev = qeth_netdev_by_devno(read_dev_no); + if (*dev == NULL) + return -ENODEV; + card = (struct qeth_card *)(*dev)->priv; + if (!card) + return -ENODEV; + if ((assist_cb == NULL) || (data_cb == NULL)) + return -EINVAL; + card->osn_info.assist_cb = assist_cb; + card->osn_info.data_cb = data_cb; + return 0; +} + +void +qeth_osn_deregister(struct net_device * dev) +{ + struct qeth_card *card; + + QETH_DBF_TEXT(trace, 2, "osndereg"); + if (!dev) + return; + card = (struct qeth_card *)dev->priv; + if (!card) + return; + card->osn_info.assist_cb = NULL; + card->osn_info.data_cb = NULL; + return; +} + static void qeth_delete_mc_addresses(struct qeth_card *card) { @@ -5712,6 +5901,12 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p) QETH_DBF_TEXT(trace, 3, "setmcLY3"); return -EOPNOTSUPP; } + if (card->info.type == QETH_CARD_TYPE_OSN) { + PRINT_WARN("Setting MAC address on %s is not supported.\n", + dev->name); + QETH_DBF_TEXT(trace, 3, "setmcOSN"); + return -EOPNOTSUPP; + } QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card)); QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN); rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]); @@ -6088,9 +6283,8 @@ qeth_netdev_init(struct net_device *dev) qeth_get_hlen(card->info.link_type) + card->options.add_hhlen; dev->addr_len = OSA_ADDR_LEN; dev->mtu = card->info.initial_mtu; - - SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops); - + if (card->info.type != QETH_CARD_TYPE_OSN) + SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops); SET_MODULE_OWNER(dev); return 0; } @@ -6107,6 +6301,7 @@ qeth_init_func_level(struct qeth_card *card) QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT; } else { if (card->info.type == QETH_CARD_TYPE_IQD) + /*FIXME:why do we have same values for dis and ena for osae??? */ card->info.func_level = QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT; else @@ -6136,7 +6331,7 @@ retry: ccw_device_set_online(CARD_WDEV(card)); ccw_device_set_online(CARD_DDEV(card)); } - rc = qeth_qdio_clear_card(card,card->info.type==QETH_CARD_TYPE_OSAE); + rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD); if (rc == -ERESTARTSYS) { QETH_DBF_TEXT(setup, 2, "break1"); return rc; @@ -6188,8 +6383,8 @@ retry: card->dev = qeth_get_netdevice(card->info.type, card->info.link_type); if (!card->dev){ - qeth_qdio_clear_card(card, card->info.type == - QETH_CARD_TYPE_OSAE); + qeth_qdio_clear_card(card, card->info.type != + QETH_CARD_TYPE_IQD); rc = -ENODEV; QETH_DBF_TEXT_(setup, 2, "6err%d", rc); goto out; @@ -6476,6 +6671,9 @@ qeth_query_ipassists_cb(struct qeth_card *card, struct qeth_reply *reply, if (cmd->hdr.prot_version == QETH_PROT_IPV4) { card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; + /* Disable IPV6 support hard coded for Hipersockets */ + if(card->info.type == QETH_CARD_TYPE_IQD) + card->options.ipa4.supported_funcs &= ~IPA_IPV6; } else { #ifdef CONFIG_QETH_IPV6 card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; @@ -7038,14 +7236,16 @@ qeth_setrouting_v6(struct qeth_card *card) } int -qeth_set_large_send(struct qeth_card *card) +qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type) { int rc = 0; - if (card->dev == NULL) + if (card->dev == NULL) { + card->options.large_send = type; return 0; - + } netif_stop_queue(card->dev); + card->options.large_send = type; switch (card->options.large_send) { case QETH_LARGE_SEND_EDDP: card->dev->features |= NETIF_F_TSO | NETIF_F_SG; @@ -7066,7 +7266,6 @@ qeth_set_large_send(struct qeth_card *card) card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); break; } - netif_wake_queue(card->dev); return rc; } @@ -7092,6 +7291,8 @@ qeth_softsetup_card(struct qeth_card *card) return rc; } else card->lan_online = 1; + if (card->info.type==QETH_CARD_TYPE_OSN) + goto out; if (card->options.layer2) { card->dev->features |= NETIF_F_HW_VLAN_FILTER | @@ -7263,7 +7464,8 @@ 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) { + if (recovery_mode && + card->info.type != QETH_CARD_TYPE_OSN) { qeth_stop(card->dev); } else { rtnl_lock(); @@ -7445,7 +7647,8 @@ qeth_start_again(struct qeth_card *card, int recovery_mode) { QETH_DBF_TEXT(setup ,2, "startag"); - if(recovery_mode) { + if (recovery_mode && + card->info.type != QETH_CARD_TYPE_OSN) { qeth_open(card->dev); } else { rtnl_lock(); @@ -7477,33 +7680,36 @@ qeth_start_again(struct qeth_card *card, int recovery_mode) static void qeth_make_parameters_consistent(struct qeth_card *card) { - if (card->options.layer2) { - if (card->info.type == QETH_CARD_TYPE_IQD) { - PRINT_ERR("Device %s does not support " \ - "layer 2 functionality. " \ - "Ignoring layer2 option.\n",CARD_BUS_ID(card)); - } - IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER, - "Routing options are"); + if (card->options.layer2 == 0) + return; + if (card->info.type == QETH_CARD_TYPE_OSN) + return; + if (card->info.type == QETH_CARD_TYPE_IQD) { + PRINT_ERR("Device %s does not support layer 2 functionality." \ + " Ignoring layer2 option.\n",CARD_BUS_ID(card)); + card->options.layer2 = 0; + return; + } + IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER, + "Routing options are"); #ifdef CONFIG_QETH_IPV6 - IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER, - "Routing options are"); + IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER, + "Routing options are"); #endif - IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING, - QETH_CHECKSUM_DEFAULT, - "Checksumming options are"); - IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS, - QETH_TR_BROADCAST_ALLRINGS, - "Broadcast mode options are"); - IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL, - QETH_TR_MACADDR_NONCANONICAL, - "Canonical MAC addr options are"); - IGNORE_PARAM_NEQ(fake_broadcast, 0, 0, - "Broadcast faking options are"); - IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN, - DEFAULT_ADD_HHLEN,"Option add_hhlen is"); - IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is"); - } + IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING, + QETH_CHECKSUM_DEFAULT, + "Checksumming options are"); + IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS, + QETH_TR_BROADCAST_ALLRINGS, + "Broadcast mode options are"); + IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL, + QETH_TR_MACADDR_NONCANONICAL, + "Canonical MAC addr options are"); + IGNORE_PARAM_NEQ(fake_broadcast, 0, 0, + "Broadcast faking options are"); + IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN, + DEFAULT_ADD_HHLEN,"Option add_hhlen is"); + IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is"); } @@ -7533,8 +7739,7 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) return -EIO; } - if (card->options.layer2) - qeth_make_parameters_consistent(card); + qeth_make_parameters_consistent(card); if ((rc = qeth_hardsetup_card(card))){ QETH_DBF_TEXT_(setup, 2, "2err%d", rc); @@ -7593,6 +7798,7 @@ qeth_set_online(struct ccwgroup_device *gdev) 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}, + {CCW_DEVICE(0x1731, 0x06), driver_info:QETH_CARD_TYPE_OSN}, {}, }; MODULE_DEVICE_TABLE(ccw, qeth_ids); @@ -7730,7 +7936,7 @@ qeth_arp_constructor(struct neighbour *neigh) goto out; rcu_read_lock(); - in_dev = rcu_dereference(__in_dev_get(dev)); + in_dev = __in_dev_get_rcu(dev); if (in_dev == NULL) { rcu_read_unlock(); return -EINVAL; @@ -8120,20 +8326,22 @@ static struct notifier_block qeth_ip6_notifier = { #endif static int -qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +__qeth_reboot_event_card(struct device *dev, void *data) { - - struct device *entry; struct qeth_card *card; - down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - list_for_each_entry(entry, &qeth_ccwgroup_driver.driver.devices, - driver_list) { - card = (struct qeth_card *) entry->driver_data; - qeth_clear_ip_list(card, 0, 0); - qeth_qdio_clear_card(card, 0); - } - up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); + card = (struct qeth_card *) dev->driver_data; + qeth_clear_ip_list(card, 0, 0); + qeth_qdio_clear_card(card, 0); + return 0; +} + +static int +qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + + driver_for_each_device(&qeth_ccwgroup_driver.driver, NULL, NULL, + __qeth_reboot_event_card); return NOTIFY_DONE; } @@ -8255,7 +8463,6 @@ qeth_init(void) { int rc=0; - qeth_eyecatcher(); PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", version, VERSION_QETH_C, VERSION_QETH_H, VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, @@ -8336,7 +8543,9 @@ again: printk("qeth: removed\n"); } -EXPORT_SYMBOL(qeth_eyecatcher); +EXPORT_SYMBOL(qeth_osn_register); +EXPORT_SYMBOL(qeth_osn_deregister); +EXPORT_SYMBOL(qeth_osn_assist); module_init(qeth_init); module_exit(qeth_exit); MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c index f685ecc7da9..30e053d3cac 100644 --- a/drivers/s390/net/qeth_mpc.c +++ b/drivers/s390/net/qeth_mpc.c @@ -11,7 +11,7 @@ #include <asm/cio.h> #include "qeth_mpc.h" -const char *VERSION_QETH_MPC_C = "$Revision: 1.11 $"; +const char *VERSION_QETH_MPC_C = "$Revision: 1.12 $"; unsigned char IDX_ACTIVATE_READ[]={ 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00, @@ -138,7 +138,9 @@ unsigned char IPA_PDU_HEADER[]={ sizeof(struct qeth_ipa_cmd)%256, 0x00, sizeof(struct qeth_ipa_cmd)/256, - sizeof(struct qeth_ipa_cmd),0x05, 0x77,0x77,0x77,0x77, + sizeof(struct qeth_ipa_cmd)%256, + 0x05, + 0x77,0x77,0x77,0x77, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x01,0x00, sizeof(struct qeth_ipa_cmd)/256, diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h index 3d916b5c5d0..7edc5f1fc0d 100644 --- a/drivers/s390/net/qeth_mpc.h +++ b/drivers/s390/net/qeth_mpc.h @@ -46,13 +46,16 @@ extern unsigned char IPA_PDU_HEADER[]; /* IP Assist related definitions */ /*****************************************************************************/ #define IPA_CMD_INITIATOR_HOST 0x00 -#define IPA_CMD_INITIATOR_HYDRA 0x01 +#define IPA_CMD_INITIATOR_OSA 0x01 +#define IPA_CMD_INITIATOR_HOST_REPLY 0x80 +#define IPA_CMD_INITIATOR_OSA_REPLY 0x81 #define IPA_CMD_PRIM_VERSION_NO 0x01 enum qeth_card_types { QETH_CARD_TYPE_UNKNOWN = 0, QETH_CARD_TYPE_OSAE = 10, QETH_CARD_TYPE_IQD = 1234, + QETH_CARD_TYPE_OSN = 11, }; #define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18 @@ -61,6 +64,7 @@ enum qeth_link_types { QETH_LINK_TYPE_FAST_ETH = 0x01, QETH_LINK_TYPE_HSTR = 0x02, QETH_LINK_TYPE_GBIT_ETH = 0x03, + QETH_LINK_TYPE_OSN = 0x04, QETH_LINK_TYPE_10GBIT_ETH = 0x10, QETH_LINK_TYPE_LANE_ETH100 = 0x81, QETH_LINK_TYPE_LANE_TR = 0x82, @@ -111,6 +115,9 @@ enum qeth_ipa_cmds { IPA_CMD_DELGMAC = 0x24, IPA_CMD_SETVLAN = 0x25, IPA_CMD_DELVLAN = 0x26, + IPA_CMD_SETCCID = 0x41, + IPA_CMD_DELCCID = 0x42, + IPA_CMD_MODCCID = 0x43, IPA_CMD_SETIP = 0xb1, IPA_CMD_DELIP = 0xb7, IPA_CMD_QIPASSIST = 0xb2, @@ -437,8 +444,9 @@ enum qeth_ipa_arp_return_codes { #define QETH_ARP_DATA_SIZE 3968 #define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8) /* Helper functions */ -#define IS_IPA_REPLY(cmd) (cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) - +#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \ + (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY)) + /*****************************************************************************/ /* END OF IP Assist related definitions */ /*****************************************************************************/ @@ -483,6 +491,7 @@ extern unsigned char ULP_ENABLE[]; /* Layer 2 defintions */ #define QETH_PROT_LAYER2 0x08 #define QETH_PROT_TCPIP 0x03 +#define QETH_PROT_OSN2 0x0a #define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50) #define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19) diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c index 04719196fd2..f2ccfea8fdb 100644 --- a/drivers/s390/net/qeth_proc.c +++ b/drivers/s390/net/qeth_proc.c @@ -27,23 +27,33 @@ const char *VERSION_QETH_PROC_C = "$Revision: 1.13 $"; #define QETH_PROCFILE_NAME "qeth" static struct proc_dir_entry *qeth_procfile; +static int +qeth_procfile_seq_match(struct device *dev, void *data) +{ + return 1; +} + static void * qeth_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct list_head *next_card = NULL; - int i = 0; + struct device *dev; + loff_t nr; down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); - if (*offset == 0) + nr = *offset; + if (nr == 0) return SEQ_START_TOKEN; - /* get card at pos *offset */ - list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices) - if (++i == *offset) - return next_card; + dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, + NULL, qeth_procfile_seq_match); - return NULL; + /* get card at pos *offset */ + nr = *offset; + while (nr-- > 1 && dev) + dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, + NULL, qeth_procfile_seq_match); + return (void *) dev; } static void @@ -55,23 +65,21 @@ qeth_procfile_seq_stop(struct seq_file *s, void* it) static void * qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { - struct list_head *next_card = NULL; - struct list_head *current_card; + struct device *prev, *next; if (it == SEQ_START_TOKEN) { - next_card = qeth_ccwgroup_driver.driver.devices.next; - if (next_card->next == next_card) /* list empty */ - return NULL; - (*offset)++; - } else { - current_card = (struct list_head *)it; - if (current_card->next == &qeth_ccwgroup_driver.driver.devices) - return NULL; /* end of list reached */ - next_card = current_card->next; - (*offset)++; + next = driver_find_device(&qeth_ccwgroup_driver.driver, + NULL, NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } - - return next_card; + prev = (struct device *) it; + next = driver_find_device(&qeth_ccwgroup_driver.driver, + prev, NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } static inline const char * @@ -126,7 +134,7 @@ qeth_procfile_seq_show(struct seq_file *s, void *it) "-------------- ---- ------ ---------- ---- " "---- ----- -----\n"); } else { - device = list_entry(it, struct device, driver_list); + device = (struct device *) it; card = device->driver_data; seq_printf(s, "%s/%s/%s x%02X %-10s %-14s %-4i ", CARD_RDEV_ID(card), @@ -180,17 +188,20 @@ static struct proc_dir_entry *qeth_perf_procfile; static void * qeth_perf_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct list_head *next_card = NULL; - int i = 0; + struct device *dev = NULL; + int nr; down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); /* get card at pos *offset */ - list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){ - if (i == *offset) - return next_card; - i++; - } - return NULL; + dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, + qeth_procfile_seq_match); + + /* get card at pos *offset */ + nr = *offset; + while (nr-- > 1 && dev) + dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, + NULL, qeth_procfile_seq_match); + return (void *) dev; } static void @@ -202,12 +213,14 @@ qeth_perf_procfile_seq_stop(struct seq_file *s, void* it) static void * qeth_perf_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { - struct list_head *current_card = (struct list_head *)it; + struct device *prev, *next; - if (current_card->next == &qeth_ccwgroup_driver.driver.devices) - return NULL; /* end of list reached */ - (*offset)++; - return current_card->next; + prev = (struct device *) it; + next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, + NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } static int @@ -216,7 +229,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) struct device *device; struct qeth_card *card; - device = list_entry(it, struct device, driver_list); + device = (struct device *) it; card = device->driver_data; seq_printf(s, "For card with devnos %s/%s/%s (%s):\n", CARD_RDEV_ID(card), @@ -318,8 +331,8 @@ static struct proc_dir_entry *qeth_ipato_procfile; static void * qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) { - struct list_head *next_card = NULL; - int i = 0; + struct device *dev; + loff_t nr; down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); /* TODO: finish this */ @@ -328,13 +341,16 @@ qeth_ipato_procfile_seq_start(struct seq_file *s, loff_t *offset) * output driver settings then; * else output setting for respective card */ + + dev = driver_find_device(&qeth_ccwgroup_driver.driver, NULL, NULL, + qeth_procfile_seq_match); + /* get card at pos *offset */ - list_for_each(next_card, &qeth_ccwgroup_driver.driver.devices){ - if (i == *offset) - return next_card; - i++; - } - return NULL; + nr = *offset; + while (nr-- > 1 && dev) + dev = driver_find_device(&qeth_ccwgroup_driver.driver, dev, + NULL, qeth_procfile_seq_match); + return (void *) dev; } static void @@ -346,18 +362,14 @@ qeth_ipato_procfile_seq_stop(struct seq_file *s, void* it) static void * qeth_ipato_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset) { - struct list_head *current_card = (struct list_head *)it; + struct device *prev, *next; - /* TODO: finish this */ - /* - * maybe SEQ_SATRT_TOKEN can be returned for offset 0 - * output driver settings then; - * else output setting for respective card - */ - if (current_card->next == &qeth_ccwgroup_driver.driver.devices) - return NULL; /* end of list reached */ - (*offset)++; - return current_card->next; + prev = (struct device *) it; + next = driver_find_device(&qeth_ccwgroup_driver.driver, prev, + NULL, qeth_procfile_seq_match); + if (next) + (*offset)++; + return (void *) next; } static int @@ -372,7 +384,7 @@ qeth_ipato_procfile_seq_show(struct seq_file *s, void *it) * output driver settings then; * else output setting for respective card */ - device = list_entry(it, struct device, driver_list); + device = (struct device *) it; card = device->driver_data; return 0; diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 98bedb0cb38..f91a02db574 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $) + * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.55 $) * * Linux on zSeries OSA Express and HiperSockets support * This file contains code related to sysfs. @@ -20,7 +20,7 @@ #include "qeth_mpc.h" #include "qeth_fs.h" -const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $"; +const char *VERSION_QETH_SYS_C = "$Revision: 1.55 $"; /*****************************************************************************/ /* */ @@ -722,10 +722,13 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c if (!card) return -EINVAL; + if (card->info.type == QETH_CARD_TYPE_IQD) { + PRINT_WARN("Layer2 on Hipersockets is not supported! \n"); + return -EPERM; + } if (((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) || - (card->info.type != QETH_CARD_TYPE_OSAE)) + (card->state != CARD_STATE_RECOVER))) return -EPERM; i = simple_strtoul(buf, &tmp, 16); @@ -771,9 +774,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con if (!card) return -EINVAL; - tmp = strsep((char **) &buf, "\n"); - if (!strcmp(tmp, "no")){ type = QETH_LARGE_SEND_NO; } else if (!strcmp(tmp, "EDDP")) { @@ -786,10 +787,8 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con } if (card->options.large_send == type) return count; - card->options.large_send = type; - if ((rc = qeth_set_large_send(card))) + if ((rc = qeth_set_large_send(card, type))) return rc; - return count; } @@ -938,6 +937,19 @@ static struct attribute_group qeth_device_attr_group = { .attrs = (struct attribute **)qeth_device_attrs, }; +static struct device_attribute * qeth_osn_device_attrs[] = { + &dev_attr_state, + &dev_attr_chpid, + &dev_attr_if_name, + &dev_attr_card_type, + &dev_attr_buffer_count, + &dev_attr_recover, + NULL, +}; + +static struct attribute_group qeth_osn_device_attr_group = { + .attrs = (struct attribute **)qeth_osn_device_attrs, +}; #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \ struct device_attribute dev_attr_##_id = { \ @@ -1668,7 +1680,12 @@ int qeth_create_device_attributes(struct device *dev) { int ret; + struct qeth_card *card = dev->driver_data; + if (card->info.type == QETH_CARD_TYPE_OSN) + return sysfs_create_group(&dev->kobj, + &qeth_osn_device_attr_group); + if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group))) return ret; if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){ @@ -1694,6 +1711,12 @@ qeth_create_device_attributes(struct device *dev) void qeth_remove_device_attributes(struct device *dev) { + struct qeth_card *card = dev->driver_data; + + if (card->info.type == QETH_CARD_TYPE_OSN) + return sysfs_remove_group(&dev->kobj, + &qeth_osn_device_attr_group); + sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); |