diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-28 09:05:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-28 09:05:25 -0700 |
commit | e5dfa9282f3db461a896a6692b529e1823ba98c6 (patch) | |
tree | 574d23cebc57c657373b0e1b6692c047aba8dd6e /drivers/s390/net/qeth_main.c | |
parent | 5dd962494f76fb3ef1196cd420b5d6260d7a3766 (diff) | |
parent | b2ab040db85835e54c7559533df7f85902617926 (diff) |
Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
Diffstat (limited to 'drivers/s390/net/qeth_main.c')
-rw-r--r-- | drivers/s390/net/qeth_main.c | 419 |
1 files changed, 318 insertions, 101 deletions
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index bd28e2438d7..692003c9f89 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -196,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) { @@ -1024,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; } /** @@ -1113,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++; @@ -1149,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); @@ -1158,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; @@ -1660,6 +1664,8 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) netif_carrier_on(card->dev); 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; @@ -1721,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) { @@ -1737,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); @@ -1768,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, @@ -1778,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"); @@ -1810,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); @@ -1821,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, @@ -1848,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), @@ -1858,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; @@ -2010,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; @@ -2100,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; } @@ -2138,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; @@ -2146,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) { @@ -2453,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); @@ -2465,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; @@ -3150,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 @@ -3466,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; } @@ -3491,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); } @@ -3655,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; @@ -3693,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) || @@ -3782,13 +3878,16 @@ static inline int qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, struct qeth_hdr **hdr, int ipv) { - int rc; + 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; @@ -4291,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); @@ -4320,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) { @@ -4381,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; @@ -5004,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) || @@ -5329,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); @@ -5370,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) { @@ -5700,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]); @@ -6076,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; } @@ -6095,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 @@ -6124,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; @@ -6176,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; @@ -7084,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 | @@ -7255,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(); @@ -7437,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(); @@ -7469,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"); } @@ -7525,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); @@ -7585,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); @@ -8329,6 +8543,9 @@ again: printk("qeth: removed\n"); } +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>"); |