diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/net/ctcm_fsms.c | 11 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_main.c | 3 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_mpc.c | 12 | ||||
-rw-r--r-- | drivers/s390/net/lcs.c | 12 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core.h | 1 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 110 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_mpc.c | 1 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_mpc.h | 14 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 7 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 40 |
10 files changed, 174 insertions, 37 deletions
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index 2d602207541b..a69766900a17 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c @@ -1341,6 +1341,12 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg) spin_unlock(&ch->collect_lock); clear_normalized_cda(&ch->ccw[1]); + + CTCM_PR_DBGDATA("ccwcda=0x%p data=0x%p\n", + (void *)(unsigned long)ch->ccw[1].cda, + ch->trans_skb->data); + ch->ccw[1].count = ch->max_bufsize; + if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) { dev_kfree_skb_any(ch->trans_skb); ch->trans_skb = NULL; @@ -1350,6 +1356,11 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg) fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); return; } + + CTCM_PR_DBGDATA("ccwcda=0x%p data=0x%p\n", + (void *)(unsigned long)ch->ccw[1].cda, + ch->trans_skb->data); + ch->ccw[1].count = ch->trans_skb->len; fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); ch->prof.send_stamp = current_kernel_time(); /* xtime */ diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 5cb93a8e3403..11f3b071f305 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -562,6 +562,9 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb) skb_queue_tail(&ch->io_queue, skb); ccw_idx = 3; } + if (do_debug_ccw) + ctcmpc_dumpit((char *)&ch->ccw[ccw_idx], + sizeof(struct ccw1) * 3); ch->retry = 0; fsm_newstate(ch->fsm, CTC_STATE_TX); fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index da4c747335e7..ac7975b7a837 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -53,8 +53,8 @@ #include <linux/moduleparam.h> #include <asm/idals.h> -#include "ctcm_mpc.h" #include "ctcm_main.h" +#include "ctcm_mpc.h" #include "ctcm_fsms.h" static const struct xid2 init_xid = { @@ -132,7 +132,7 @@ void ctcmpc_dumpit(char *buf, int len) __u32 ct, sw, rm, dup; char *ptr, *rptr; char tbuf[82], tdup[82]; - #if (UTS_MACHINE == s390x) + #ifdef CONFIG_64BIT char addr[22]; #else char addr[12]; @@ -149,8 +149,8 @@ void ctcmpc_dumpit(char *buf, int len) for (ct = 0; ct < len; ct++, ptr++, rptr++) { if (sw == 0) { - #if (UTS_MACHINE == s390x) - sprintf(addr, "%16.16lx", (__u64)rptr); + #ifdef CONFIG_64BIT + sprintf(addr, "%16.16llx", (__u64)rptr); #else sprintf(addr, "%8.8X", (__u32)rptr); #endif @@ -164,8 +164,8 @@ void ctcmpc_dumpit(char *buf, int len) if (sw == 8) strcat(bhex, " "); - #if (UTS_MACHINE == s390x) - sprintf(tbuf, "%2.2lX", (__u64)*ptr); + #if CONFIG_64BIT + sprintf(tbuf, "%2.2llX", (__u64)*ptr); #else sprintf(tbuf, "%2.2X", (__u32)*ptr); #endif diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 863fc2197155..687efe4d589a 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -2240,7 +2240,7 @@ __lcs_shutdown_device(struct ccwgroup_device *ccwgdev, int recovery_mode) { struct lcs_card *card; enum lcs_dev_states recover_state; - int ret; + int ret = 0, ret2 = 0, ret3 = 0; LCS_DBF_TEXT(3, setup, "shtdndev"); card = dev_get_drvdata(&ccwgdev->dev); @@ -2255,13 +2255,15 @@ __lcs_shutdown_device(struct ccwgroup_device *ccwgdev, int recovery_mode) recover_state = card->state; ret = lcs_stop_device(card->dev); - ret = ccw_device_set_offline(card->read.ccwdev); - ret = ccw_device_set_offline(card->write.ccwdev); + ret2 = ccw_device_set_offline(card->read.ccwdev); + ret3 = ccw_device_set_offline(card->write.ccwdev); + if (!ret) + ret = (ret2) ? ret2 : ret3; + if (ret) + LCS_DBF_TEXT_(3, setup, "1err:%d", ret); if (recover_state == DEV_STATE_UP) { card->state = DEV_STATE_RECOVER; } - if (ret) - return ret; return 0; } diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 4abc79d3963f..ec7921b5138e 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -906,6 +906,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, char); struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); int qeth_mdio_read(struct net_device *, int, int); int qeth_snmp_command(struct qeth_card *, char __user *); +int qeth_query_oat_command(struct qeth_card *, char __user *); struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32); int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 9c3f38da4c01..120955c66410 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -26,6 +26,7 @@ #include <asm/ebcdic.h> #include <asm/io.h> #include <asm/sysinfo.h> +#include <asm/compat.h> #include "qeth_core.h" @@ -50,6 +51,7 @@ static struct kmem_cache *qeth_qdio_outbuf_cache; static struct device *qeth_core_root_dev; static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY; static struct lock_class_key qdio_out_skb_queue_key; +static struct mutex qeth_mod_mutex; static void qeth_send_control_data_cb(struct qeth_channel *, struct qeth_cmd_buffer *); @@ -677,6 +679,7 @@ void qeth_release_buffer(struct qeth_channel *channel, iob->callback = qeth_send_control_data_cb; iob->rc = 0; spin_unlock_irqrestore(&channel->iob_lock, flags); + wake_up(&channel->wait_q); } EXPORT_SYMBOL_GPL(qeth_release_buffer); @@ -2942,8 +2945,8 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; } QETH_DBF_TEXT(SETUP, 2, "suppenbl"); - QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported); - QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled); + QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported); + QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled); return 0; } @@ -4319,7 +4322,7 @@ static int qeth_snmp_command_cb(struct qeth_card *card, /* check if there is enough room in userspace */ if ((qinfo->udata_len - qinfo->udata_offset) < data_len) { QETH_CARD_TEXT_(card, 4, "scer3%i", -ENOMEM); - cmd->hdr.return_code = -ENOMEM; + cmd->hdr.return_code = IPA_RC_ENOMEM; return 0; } QETH_CARD_TEXT_(card, 4, "snore%i", @@ -4402,6 +4405,104 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) } EXPORT_SYMBOL_GPL(qeth_snmp_command); +static int qeth_setadpparms_query_oat_cb(struct qeth_card *card, + struct qeth_reply *reply, unsigned long data) +{ + struct qeth_ipa_cmd *cmd; + struct qeth_qoat_priv *priv; + char *resdata; + int resdatalen; + + QETH_CARD_TEXT(card, 3, "qoatcb"); + + cmd = (struct qeth_ipa_cmd *)data; + priv = (struct qeth_qoat_priv *)reply->param; + resdatalen = cmd->data.setadapterparms.hdr.cmdlength; + resdata = (char *)data + 28; + + if (resdatalen > (priv->buffer_len - priv->response_len)) { + cmd->hdr.return_code = IPA_RC_FFFF; + return 0; + } + + memcpy((priv->buffer + priv->response_len), resdata, + resdatalen); + priv->response_len += resdatalen; + + if (cmd->data.setadapterparms.hdr.seq_no < + cmd->data.setadapterparms.hdr.used_total) + return 1; + return 0; +} + +int qeth_query_oat_command(struct qeth_card *card, char __user *udata) +{ + int rc = 0; + struct qeth_cmd_buffer *iob; + struct qeth_ipa_cmd *cmd; + struct qeth_query_oat *oat_req; + struct qeth_query_oat_data oat_data; + struct qeth_qoat_priv priv; + void __user *tmp; + + QETH_CARD_TEXT(card, 3, "qoatcmd"); + + if (!qeth_adp_supported(card, IPA_SETADP_QUERY_OAT)) { + rc = -EOPNOTSUPP; + goto out; + } + + if (copy_from_user(&oat_data, udata, + sizeof(struct qeth_query_oat_data))) { + rc = -EFAULT; + goto out; + } + + priv.buffer_len = oat_data.buffer_len; + priv.response_len = 0; + priv.buffer = kzalloc(oat_data.buffer_len, GFP_KERNEL); + if (!priv.buffer) { + rc = -ENOMEM; + goto out; + } + + iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_OAT, + sizeof(struct qeth_ipacmd_setadpparms_hdr) + + sizeof(struct qeth_query_oat)); + cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); + oat_req = &cmd->data.setadapterparms.data.query_oat; + oat_req->subcmd_code = oat_data.command; + + rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_query_oat_cb, + &priv); + if (!rc) { + if (is_compat_task()) + tmp = compat_ptr(oat_data.ptr); + else + tmp = (void __user *)(unsigned long)oat_data.ptr; + + if (copy_to_user(tmp, priv.buffer, + priv.response_len)) { + rc = -EFAULT; + goto out_free; + } + + oat_data.response_len = priv.response_len; + + if (copy_to_user(udata, &oat_data, + sizeof(struct qeth_query_oat_data))) + rc = -EFAULT; + } else + if (rc == IPA_RC_FFFF) + rc = -EFAULT; + +out_free: + kfree(priv.buffer); +out: + return rc; +} +EXPORT_SYMBOL_GPL(qeth_query_oat_command); + static inline int qeth_get_qdio_q_format(struct qeth_card *card) { switch (card->info.type) { @@ -4940,6 +5041,7 @@ int qeth_core_load_discipline(struct qeth_card *card, enum qeth_discipline_id discipline) { int rc = 0; + mutex_lock(&qeth_mod_mutex); switch (discipline) { case QETH_DISCIPLINE_LAYER3: card->discipline.ccwgdriver = try_then_request_module( @@ -4957,6 +5059,7 @@ int qeth_core_load_discipline(struct qeth_card *card, "support discipline %d\n", discipline); rc = -EINVAL; } + mutex_unlock(&qeth_mod_mutex); return rc; } @@ -5440,6 +5543,7 @@ static int __init qeth_core_init(void) pr_info("loading core functions\n"); INIT_LIST_HEAD(&qeth_core_card_list.list); rwlock_init(&qeth_core_card_list.rwlock); + mutex_init(&qeth_mod_mutex); rc = qeth_register_dbf_views(); if (rc) diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c index ec24901c802c..7fab6544def6 100644 --- a/drivers/s390/net/qeth_core_mpc.c +++ b/drivers/s390/net/qeth_core_mpc.c @@ -207,6 +207,7 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = { {IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"}, {IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"}, {IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"}, + {IPA_RC_ENOMEM, "Memory problem"}, {IPA_RC_FFFF, "Unknown Error"} }; diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index e5a9d1c03839..ff41e42004ac 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -190,6 +190,7 @@ enum qeth_ipa_return_codes { IPA_RC_MC_ADDR_ALREADY_DEFINED = 0xe013, IPA_RC_LAN_OFFLINE = 0xe080, IPA_RC_INVALID_IP_VERSION2 = 0xf001, + IPA_RC_ENOMEM = 0xfffe, IPA_RC_FFFF = 0xffff }; /* for DELIP */ @@ -249,6 +250,7 @@ enum qeth_ipa_setadp_cmd { IPA_SETADP_SET_PROMISC_MODE = 0x00000800L, IPA_SETADP_SET_DIAG_ASSIST = 0x00002000L, IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L, + IPA_SETADP_QUERY_OAT = 0x00080000L, }; enum qeth_ipa_mac_ops { CHANGE_ADDR_READ_MAC = 0, @@ -398,6 +400,17 @@ struct qeth_set_access_ctrl { __u32 subcmd_code; } __attribute__((packed)); +struct qeth_query_oat { + __u32 subcmd_code; + __u8 reserved[12]; +} __packed; + +struct qeth_qoat_priv { + __u32 buffer_len; + __u32 response_len; + char *buffer; +}; + struct qeth_ipacmd_setadpparms_hdr { __u32 supp_hw_cmds; __u32 reserved1; @@ -417,6 +430,7 @@ struct qeth_ipacmd_setadpparms { struct qeth_change_addr change_addr; struct qeth_snmp_cmd snmp; struct qeth_set_access_ctrl set_access_ctrl; + struct qeth_query_oat query_oat; __u32 mode; } data; } __attribute__ ((packed)); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index c12967133114..0e7c29d1d7ef 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -75,6 +75,9 @@ static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) mii_data->val_out = qeth_mdio_read(dev, mii_data->phy_id, mii_data->reg_num); break; + case SIOC_QETH_QUERY_OAT: + rc = qeth_query_oat_command(card, rq->ifr_ifru.ifru_data); + break; default: rc = -EOPNOTSUPP; } @@ -573,7 +576,6 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card, default: break; } - cmd->hdr.return_code = -EIO; } else { card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; memcpy(card->dev->dev_addr, cmd->data.setdelmac.mac, @@ -602,7 +604,6 @@ static int qeth_l2_send_delmac_cb(struct qeth_card *card, cmd = (struct qeth_ipa_cmd *) data; if (cmd->hdr.return_code) { QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code); - cmd->hdr.return_code = -EIO; return 0; } card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; @@ -679,7 +680,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]); if (!rc) rc = qeth_l2_send_setmac(card, addr->sa_data); - return rc; + return rc ? -EINVAL : 0; } static void qeth_l2_set_multicast_list(struct net_device *dev) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 9648e4e68337..f85921607686 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -28,6 +28,8 @@ #include <net/ip.h> #include <net/arp.h> +#include <net/route.h> +#include <net/ip6_fib.h> #include <net/ip6_checksum.h> #include <net/iucv/af_iucv.h> @@ -2428,7 +2430,7 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, if ((qinfo->udata_len - qinfo->udata_offset) < esize) { QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM); - cmd->hdr.return_code = -ENOMEM; + cmd->hdr.return_code = IPA_RC_ENOMEM; goto out_error; } @@ -2743,6 +2745,9 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) mii_data->phy_id, mii_data->reg_num); break; + case SIOC_QETH_QUERY_OAT: + rc = qeth_query_oat_command(card, rq->ifr_ifru.ifru_data); + break; default: rc = -EOPNOTSUPP; } @@ -2832,7 +2837,6 @@ static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card, static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, struct sk_buff *skb, int ipv, int cast_type) { - struct neighbour *n = NULL; struct dst_entry *dst; memset(hdr, 0, sizeof(struct qeth_hdr)); @@ -2855,33 +2859,29 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, rcu_read_lock(); dst = skb_dst(skb); - if (dst) - n = dst_get_neighbour_noref(dst); if (ipv == 4) { + struct rtable *rt = (struct rtable *) dst; + __be32 *pkey = &ip_hdr(skb)->daddr; + + if (rt->rt_gateway) + pkey = &rt->rt_gateway; + /* IPv4 */ hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type); memset(hdr->hdr.l3.dest_addr, 0, 12); - if (n) { - *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = - *((u32 *) n->primary_key); - } else { - /* fill in destination address used in ip header */ - *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = - ip_hdr(skb)->daddr; - } + *((__be32 *) (&hdr->hdr.l3.dest_addr[12])) = *pkey; } else if (ipv == 6) { + struct rt6_info *rt = (struct rt6_info *) dst; + struct in6_addr *pkey = &ipv6_hdr(skb)->daddr; + + if (!ipv6_addr_any(&rt->rt6i_gateway)) + pkey = &rt->rt6i_gateway; + /* IPv6 */ hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type); if (card->info.type == QETH_CARD_TYPE_IQD) hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU; - if (n) { - memcpy(hdr->hdr.l3.dest_addr, - n->primary_key, 16); - } else { - /* fill in destination address used in ip header */ - memcpy(hdr->hdr.l3.dest_addr, - &ipv6_hdr(skb)->daddr, 16); - } + memcpy(hdr->hdr.l3.dest_addr, pkey, 16); } else { /* passthrough */ if ((skb->dev->type == ARPHRD_IEEE802_TR) && |