diff options
Diffstat (limited to 'drivers/s390/net/qeth_core_main.c')
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 373 |
1 files changed, 155 insertions, 218 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 89e09e7b8fff..0078b5d217cc 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -62,10 +62,10 @@ static struct kmem_cache *qeth_qdio_outbuf_cache; static struct device *qeth_core_root_dev; 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 *); +static void qeth_send_control_data_cb(struct qeth_card *card, + struct qeth_channel *channel, + struct qeth_cmd_buffer *iob); static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *); static void qeth_free_buffer_pool(struct qeth_card *); static int qeth_qdio_establish(struct qeth_card *); @@ -626,80 +626,61 @@ static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc, } static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, - struct qeth_cmd_buffer *iob) + struct qeth_ipa_cmd *cmd) { - struct qeth_ipa_cmd *cmd = NULL; - QETH_CARD_TEXT(card, 5, "chkipad"); - if (IS_IPA(iob->data)) { - cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data); - if (IS_IPA_REPLY(cmd)) { - if (cmd->hdr.command != IPA_CMD_SETCCID && - cmd->hdr.command != IPA_CMD_DELCCID && - cmd->hdr.command != IPA_CMD_MODCCID && - cmd->hdr.command != IPA_CMD_SET_DIAG_ASS) - qeth_issue_ipa_msg(cmd, - cmd->hdr.return_code, card); - return cmd; + + if (IS_IPA_REPLY(cmd)) { + if (cmd->hdr.command != IPA_CMD_SETCCID && + cmd->hdr.command != IPA_CMD_DELCCID && + cmd->hdr.command != IPA_CMD_MODCCID && + cmd->hdr.command != IPA_CMD_SET_DIAG_ASS) + qeth_issue_ipa_msg(cmd, cmd->hdr.return_code, card); + return cmd; + } + + /* handle unsolicited event: */ + switch (cmd->hdr.command) { + case IPA_CMD_STOPLAN: + if (cmd->hdr.return_code == IPA_RC_VEPA_TO_VEB_TRANSITION) { + dev_err(&card->gdev->dev, + "Interface %s is down because the adjacent port is no longer in reflective relay mode\n", + QETH_CARD_IFNAME(card)); + qeth_close_dev(card); } else { - switch (cmd->hdr.command) { - case IPA_CMD_STOPLAN: - if (cmd->hdr.return_code == - IPA_RC_VEPA_TO_VEB_TRANSITION) { - dev_err(&card->gdev->dev, - "Interface %s is down because the " - "adjacent port is no longer in " - "reflective relay mode\n", - QETH_CARD_IFNAME(card)); - qeth_close_dev(card); - } else { - dev_warn(&card->gdev->dev, - "The link for interface %s on CHPID" - " 0x%X failed\n", - QETH_CARD_IFNAME(card), - card->info.chpid); - qeth_issue_ipa_msg(cmd, - cmd->hdr.return_code, card); - } - card->lan_online = 0; - netif_carrier_off(card->dev); - return NULL; - case IPA_CMD_STARTLAN: - dev_info(&card->gdev->dev, - "The link for %s on CHPID 0x%X has" - " been restored\n", - QETH_CARD_IFNAME(card), - card->info.chpid); - netif_carrier_on(card->dev); - card->lan_online = 1; - if (card->info.hwtrap) - card->info.hwtrap = 2; - qeth_schedule_recovery(card); - return NULL; - case IPA_CMD_SETBRIDGEPORT_IQD: - case IPA_CMD_SETBRIDGEPORT_OSA: - case IPA_CMD_ADDRESS_CHANGE_NOTIF: - if (card->discipline->control_event_handler - (card, cmd)) - return cmd; - else - return NULL; - case IPA_CMD_MODCCID: - return cmd; - case IPA_CMD_REGISTER_LOCAL_ADDR: - QETH_CARD_TEXT(card, 3, "irla"); - break; - case IPA_CMD_UNREGISTER_LOCAL_ADDR: - QETH_CARD_TEXT(card, 3, "urla"); - break; - default: - QETH_DBF_MESSAGE(2, "Received data is IPA " - "but not a reply!\n"); - break; - } + dev_warn(&card->gdev->dev, + "The link for interface %s on CHPID 0x%X failed\n", + QETH_CARD_IFNAME(card), card->info.chpid); + qeth_issue_ipa_msg(cmd, cmd->hdr.return_code, card); + netif_carrier_off(card->dev); } + return NULL; + case IPA_CMD_STARTLAN: + dev_info(&card->gdev->dev, + "The link for %s on CHPID 0x%X has been restored\n", + QETH_CARD_IFNAME(card), card->info.chpid); + if (card->info.hwtrap) + card->info.hwtrap = 2; + qeth_schedule_recovery(card); + return NULL; + case IPA_CMD_SETBRIDGEPORT_IQD: + case IPA_CMD_SETBRIDGEPORT_OSA: + case IPA_CMD_ADDRESS_CHANGE_NOTIF: + if (card->discipline->control_event_handler(card, cmd)) + return cmd; + return NULL; + case IPA_CMD_MODCCID: + return cmd; + case IPA_CMD_REGISTER_LOCAL_ADDR: + QETH_CARD_TEXT(card, 3, "irla"); + return NULL; + case IPA_CMD_UNREGISTER_LOCAL_ADDR: + QETH_CARD_TEXT(card, 3, "urla"); + return NULL; + default: + QETH_DBF_MESSAGE(2, "Received data is IPA but not a reply!\n"); + return cmd; } - return cmd; } void qeth_clear_ipacmd_list(struct qeth_card *card) @@ -746,18 +727,10 @@ static int qeth_check_idx_response(struct qeth_card *card, return 0; } -static struct qeth_card *CARD_FROM_CDEV(struct ccw_device *cdev) -{ - struct qeth_card *card = dev_get_drvdata(&((struct ccwgroup_device *) - dev_get_drvdata(&cdev->dev))->dev); - return card; -} - static struct qeth_cmd_buffer *__qeth_get_buffer(struct qeth_channel *channel) { __u8 index; - QETH_CARD_TEXT(CARD_FROM_CDEV(channel->ccwdev), 6, "getbuff"); index = channel->io_buf_no; do { if (channel->iob[index].state == BUF_STATE_FREE) { @@ -778,7 +751,6 @@ void qeth_release_buffer(struct qeth_channel *channel, { unsigned long flags; - QETH_CARD_TEXT(CARD_FROM_CDEV(channel->ccwdev), 6, "relbuff"); spin_lock_irqsave(&channel->iob_lock, flags); iob->state = BUF_STATE_FREE; iob->callback = qeth_send_control_data_cb; @@ -788,6 +760,13 @@ void qeth_release_buffer(struct qeth_channel *channel, } EXPORT_SYMBOL_GPL(qeth_release_buffer); +static void qeth_release_buffer_cb(struct qeth_card *card, + struct qeth_channel *channel, + struct qeth_cmd_buffer *iob) +{ + qeth_release_buffer(channel, iob); +} + static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel) { struct qeth_cmd_buffer *buffer = NULL; @@ -818,17 +797,16 @@ void qeth_clear_cmd_buffers(struct qeth_channel *channel) } EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers); -static void qeth_send_control_data_cb(struct qeth_channel *channel, - struct qeth_cmd_buffer *iob) +static void qeth_send_control_data_cb(struct qeth_card *card, + struct qeth_channel *channel, + struct qeth_cmd_buffer *iob) { - struct qeth_card *card; + struct qeth_ipa_cmd *cmd = NULL; struct qeth_reply *reply, *r; - struct qeth_ipa_cmd *cmd; unsigned long flags; int keep_reply; int rc = 0; - card = CARD_FROM_CDEV(channel->ccwdev); QETH_CARD_TEXT(card, 4, "sndctlcb"); rc = qeth_check_idx_response(card, iob->data); switch (rc) { @@ -842,16 +820,20 @@ static void qeth_send_control_data_cb(struct qeth_channel *channel, goto out; } - 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; + if (IS_IPA(iob->data)) { + cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data); + cmd = qeth_check_ipa_data(card, cmd); + if (!cmd) + goto out; + if (IS_OSN(card) && card->osn_info.assist_cb && + cmd->hdr.command != IPA_CMD_STARTLAN) { + card->osn_info.assist_cb(card->dev, cmd); + goto out; + } + } else { + /* non-IPA commands should only flow during initialization */ + if (card->state != CARD_STATE_DOWN) + goto out; } spin_lock_irqsave(&card->lock, flags); @@ -974,16 +956,15 @@ void qeth_schedule_recovery(struct qeth_card *card) } EXPORT_SYMBOL_GPL(qeth_schedule_recovery); -static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb) +static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev, + struct irb *irb) { int dstat, cstat; char *sense; - struct qeth_card *card; sense = (char *) irb->ecw; cstat = irb->scsw.cmd.cstat; dstat = irb->scsw.cmd.dstat; - card = CARD_FROM_CDEV(cdev); if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK | SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK | @@ -1023,14 +1004,11 @@ static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb) return 0; } -static long __qeth_check_irb_error(struct ccw_device *cdev, - unsigned long intparm, struct irb *irb) +static long qeth_check_irb_error(struct qeth_card *card, + struct ccw_device *cdev, unsigned long intparm, + struct irb *irb) { - struct qeth_card *card; - - card = CARD_FROM_CDEV(cdev); - - if (!card || !IS_ERR(irb)) + if (!IS_ERR(irb)) return 0; switch (PTR_ERR(irb)) { @@ -1067,10 +1045,13 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, int rc; int cstat, dstat; struct qeth_cmd_buffer *iob = NULL; + struct ccwgroup_device *gdev; struct qeth_channel *channel; struct qeth_card *card; - card = CARD_FROM_CDEV(cdev); + /* while we hold the ccwdev lock, this stays valid: */ + gdev = dev_get_drvdata(&cdev->dev); + card = dev_get_drvdata(&gdev->dev); if (!card) return; @@ -1090,7 +1071,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, if (qeth_intparm_is_iob(intparm)) iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm); - if (__qeth_check_irb_error(cdev, intparm, irb)) { + if (qeth_check_irb_error(card, cdev, intparm, irb)) { /* IO was terminated, free its resources. */ if (iob) qeth_release_buffer(iob->channel, iob); @@ -1145,7 +1126,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, channel->state = CH_STATE_DOWN; goto out; } - rc = qeth_get_problem(cdev, irb); + rc = qeth_get_problem(card, cdev, irb); if (rc) { card->read_or_write_problem = 1; qeth_clear_ipacmd_list(card); @@ -1165,7 +1146,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, __qeth_issue_next_read(card); if (iob && iob->callback) - iob->callback(iob->channel, iob); + iob->callback(card, iob->channel, iob); out: wake_up(&card->wait_q); @@ -1178,54 +1159,23 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *q, { struct sk_buff *skb; - if (skb_queue_empty(&buf->skb_list)) - goto out; - skb = skb_peek(&buf->skb_list); - while (skb) { + skb_queue_walk(&buf->skb_list, skb) { QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification); QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb); - if (be16_to_cpu(skb->protocol) == ETH_P_AF_IUCV) { - if (skb->sk) { - struct iucv_sock *iucv = iucv_sk(skb->sk); - iucv->sk_txnotify(skb, notification); - } - } - if (skb_queue_is_last(&buf->skb_list, skb)) - skb = NULL; - else - skb = skb_queue_next(&buf->skb_list, skb); + if (skb->protocol == htons(ETH_P_AF_IUCV) && skb->sk) + iucv_sk(skb->sk)->sk_txnotify(skb, notification); } -out: - return; } static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf) { - struct sk_buff *skb; - struct iucv_sock *iucv; - int notify_general_error = 0; - - if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) - notify_general_error = 1; - /* release may never happen from within CQ tasklet scope */ WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ); - skb = skb_dequeue(&buf->skb_list); - while (skb) { - QETH_CARD_TEXT(buf->q->card, 5, "skbr"); - QETH_CARD_TEXT_(buf->q->card, 5, "%lx", (long) skb); - if (notify_general_error && - be16_to_cpu(skb->protocol) == ETH_P_AF_IUCV) { - if (skb->sk) { - iucv = iucv_sk(skb->sk); - iucv->sk_txnotify(skb, TX_NOTIFY_GENERALERROR); - } - } - refcount_dec(&skb->users); - dev_kfree_skb_any(skb); - skb = skb_dequeue(&buf->skb_list); - } + if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) + qeth_notify_skbs(buf->q, buf, TX_NOTIFY_GENERALERROR); + + __skb_queue_purge(&buf->skb_list); } static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, @@ -1429,6 +1379,7 @@ static void qeth_set_initial_options(struct qeth_card *card) card->options.rx_sg_cb = QETH_RX_SG_CB; card->options.isolation = ISOLATION_MODE_NONE; card->options.cq = QETH_CQ_DISABLED; + card->options.layer = QETH_DISCIPLINE_UNDETERMINED; } static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread) @@ -1513,6 +1464,7 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev) QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); card->gdev = gdev; + dev_set_drvdata(&gdev->dev, card); CARD_RDEV(card) = gdev->cdev[0]; CARD_WDEV(card) = gdev->cdev[1]; CARD_DDEV(card) = gdev->cdev[2]; @@ -1522,7 +1474,6 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev) goto out_channel; if (qeth_setup_channel(&card->data, false)) goto out_data; - card->options.layer2 = -1; card->qeth_service_level.seq_print = qeth_core_sl_print; register_service_level(&card->qeth_service_level); return card; @@ -1532,17 +1483,17 @@ out_data: out_channel: qeth_clean_channel(&card->read); out_ip: + dev_set_drvdata(&gdev->dev, NULL); kfree(card); out: return NULL; } -static int qeth_clear_channel(struct qeth_channel *channel) +static int qeth_clear_channel(struct qeth_card *card, + struct qeth_channel *channel) { - struct qeth_card *card; int rc; - card = CARD_FROM_CDEV(channel->ccwdev); QETH_CARD_TEXT(card, 3, "clearch"); spin_lock_irq(get_ccwdev_lock(channel->ccwdev)); rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM); @@ -1560,12 +1511,11 @@ static int qeth_clear_channel(struct qeth_channel *channel) return 0; } -static int qeth_halt_channel(struct qeth_channel *channel) +static int qeth_halt_channel(struct qeth_card *card, + struct qeth_channel *channel) { - struct qeth_card *card; int rc; - card = CARD_FROM_CDEV(channel->ccwdev); QETH_CARD_TEXT(card, 3, "haltch"); spin_lock_irq(get_ccwdev_lock(channel->ccwdev)); rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM); @@ -1587,9 +1537,9 @@ static int qeth_halt_channels(struct qeth_card *card) int rc1 = 0, rc2 = 0, rc3 = 0; QETH_CARD_TEXT(card, 3, "haltchs"); - rc1 = qeth_halt_channel(&card->read); - rc2 = qeth_halt_channel(&card->write); - rc3 = qeth_halt_channel(&card->data); + rc1 = qeth_halt_channel(card, &card->read); + rc2 = qeth_halt_channel(card, &card->write); + rc3 = qeth_halt_channel(card, &card->data); if (rc1) return rc1; if (rc2) @@ -1602,9 +1552,9 @@ static int qeth_clear_channels(struct qeth_card *card) int rc1 = 0, rc2 = 0, rc3 = 0; QETH_CARD_TEXT(card, 3, "clearchs"); - rc1 = qeth_clear_channel(&card->read); - rc2 = qeth_clear_channel(&card->write); - rc3 = qeth_clear_channel(&card->data); + rc1 = qeth_clear_channel(card, &card->read); + rc2 = qeth_clear_channel(card, &card->write); + rc3 = qeth_clear_channel(card, &card->data); if (rc1) return rc1; if (rc2) @@ -1833,20 +1783,20 @@ static void qeth_init_func_level(struct qeth_card *card) } } -static int qeth_idx_activate_get_answer(struct qeth_channel *channel, - void (*idx_reply_cb)(struct qeth_channel *, - struct qeth_cmd_buffer *)) +static int qeth_idx_activate_get_answer(struct qeth_card *card, + struct qeth_channel *channel, + void (*reply_cb)(struct qeth_card *, + struct qeth_channel *, + struct qeth_cmd_buffer *)) { struct qeth_cmd_buffer *iob; int rc; - struct qeth_card *card; QETH_DBF_TEXT(SETUP, 2, "idxanswr"); - card = CARD_FROM_CDEV(channel->ccwdev); iob = qeth_get_buffer(channel); if (!iob) return -ENOMEM; - iob->callback = idx_reply_cb; + iob->callback = reply_cb; qeth_setup_ccw(channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data); wait_event(card->wait_q, @@ -1876,25 +1826,24 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel, return rc; } -static int qeth_idx_activate_channel(struct qeth_channel *channel, - void (*idx_reply_cb)(struct qeth_channel *, - struct qeth_cmd_buffer *)) +static int qeth_idx_activate_channel(struct qeth_card *card, + struct qeth_channel *channel, + void (*reply_cb)(struct qeth_card *, + struct qeth_channel *, + struct qeth_cmd_buffer *)) { - struct qeth_card *card; struct qeth_cmd_buffer *iob; __u16 temp; __u8 tmp; int rc; struct ccw_dev_id temp_devid; - card = CARD_FROM_CDEV(channel->ccwdev); - QETH_DBF_TEXT(SETUP, 2, "idxactch"); iob = qeth_get_buffer(channel); if (!iob) return -ENOMEM; - iob->callback = idx_reply_cb; + iob->callback = reply_cb; qeth_setup_ccw(channel->ccw, CCW_CMD_WRITE, IDX_ACTIVATE_SIZE, iob->data); if (channel == &card->write) { @@ -1946,7 +1895,7 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel, QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME); return -ETIME; } - return qeth_idx_activate_get_answer(channel, idx_reply_cb); + return qeth_idx_activate_get_answer(card, channel, reply_cb); } static int qeth_peer_func_level(int level) @@ -1958,10 +1907,10 @@ static int qeth_peer_func_level(int level) return level; } -static void qeth_idx_write_cb(struct qeth_channel *channel, - struct qeth_cmd_buffer *iob) +static void qeth_idx_write_cb(struct qeth_card *card, + struct qeth_channel *channel, + struct qeth_cmd_buffer *iob) { - struct qeth_card *card; __u16 temp; QETH_DBF_TEXT(SETUP , 2, "idxwrcb"); @@ -1970,7 +1919,6 @@ static void qeth_idx_write_cb(struct qeth_channel *channel, channel->state = CH_STATE_ACTIVATING; goto out; } - card = CARD_FROM_CDEV(channel->ccwdev); if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) { if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == QETH_IDX_ACT_ERR_EXCL) @@ -1996,10 +1944,10 @@ out: qeth_release_buffer(channel, iob); } -static void qeth_idx_read_cb(struct qeth_channel *channel, - struct qeth_cmd_buffer *iob) +static void qeth_idx_read_cb(struct qeth_card *card, + struct qeth_channel *channel, + struct qeth_cmd_buffer *iob) { - struct qeth_card *card; __u16 temp; QETH_DBF_TEXT(SETUP , 2, "idxrdcb"); @@ -2008,7 +1956,6 @@ static void qeth_idx_read_cb(struct qeth_channel *channel, goto out; } - card = CARD_FROM_CDEV(channel->ccwdev); if (qeth_check_idx_response(card, iob->data)) goto out; @@ -2057,7 +2004,7 @@ void qeth_prepare_control_data(struct qeth_card *card, int len, struct qeth_cmd_buffer *iob) { qeth_setup_ccw(iob->channel->ccw, CCW_CMD_WRITE, len, iob->data); - iob->callback = qeth_release_buffer; + iob->callback = qeth_release_buffer_cb; memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data), &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH); @@ -2205,7 +2152,6 @@ static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply, memcpy(&card->token.cm_filter_r, QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data), QETH_MPC_TOKEN_LENGTH); - QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); return 0; } @@ -2231,7 +2177,6 @@ static int qeth_cm_enable(struct qeth_card *card) static int qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_cmd_buffer *iob; QETH_DBF_TEXT(SETUP, 2, "cmsetpcb"); @@ -2240,7 +2185,6 @@ static int qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply, memcpy(&card->token.cm_connection_r, QETH_CM_SETUP_RESP_DEST_ADDR(iob->data), QETH_MPC_TOKEN_LENGTH); - QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); return 0; } @@ -2262,7 +2206,6 @@ static int qeth_cm_setup(struct qeth_card *card) rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob, qeth_cm_setup_cb, NULL); return rc; - } static int qeth_update_max_mtu(struct qeth_card *card, unsigned int max_mtu) @@ -2291,7 +2234,7 @@ static int qeth_update_max_mtu(struct qeth_card *card, unsigned int max_mtu) if (dev->mtu) new_mtu = dev->mtu; /* default MTUs for first setup: */ - else if (card->options.layer2) + else if (IS_LAYER2(card)) new_mtu = ETH_DATA_LEN; else new_mtu = ETH_DATA_LEN - 8; /* allow for LLC + SNAP */ @@ -2322,7 +2265,6 @@ static int qeth_get_mtu_outof_framesize(int framesize) static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - __u16 mtu, framesize; __u16 len; __u8 link_type; @@ -2350,7 +2292,6 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply, } else card->info.link_type = 0; QETH_DBF_TEXT_(SETUP, 2, "link%d", card->info.link_type); - QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); return 0; } @@ -2358,7 +2299,7 @@ static u8 qeth_mpc_select_prot_type(struct qeth_card *card) { if (IS_OSN(card)) return QETH_PROT_OSN2; - return (card->options.layer2 == 1) ? QETH_PROT_LAYER2 : QETH_PROT_TCPIP; + return IS_LAYER2(card) ? QETH_PROT_LAYER2 : QETH_PROT_TCPIP; } static int qeth_ulp_enable(struct qeth_card *card) @@ -2896,10 +2837,7 @@ static void qeth_fill_ipacmd_header(struct qeth_card *card, /* cmd->hdr.seqno is set by qeth_send_control_data() */ cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type); cmd->hdr.rel_adapter_no = (u8) card->dev->dev_port; - if (card->options.layer2) - cmd->hdr.prim_version_no = 2; - else - cmd->hdr.prim_version_no = 1; + cmd->hdr.prim_version_no = IS_LAYER2(card) ? 2 : 1; cmd->hdr.param_count = 1; cmd->hdr.prot_version = prot; } @@ -4001,8 +3939,7 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, bool is_first_elem = true; int flush_cnt = 0; - refcount_inc(&skb->users); - skb_queue_tail(&buf->skb_list, skb); + __skb_queue_tail(&buf->skb_list, skb); /* build dedicated header element */ if (hd_len) { @@ -4278,8 +4215,7 @@ static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card, if (qeth_setadpparms_inspect_rc(cmd)) return 0; - if (!card->options.layer2 || - !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) { + if (IS_LAYER3(card) || !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) { ether_addr_copy(card->dev->dev_addr, cmd->data.setadapterparms.data.change_addr.addr); card->info.mac_bits |= QETH_LAYER2_MAC_READ; @@ -4633,9 +4569,9 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata) return -EOPNOTSUPP; if ((!qeth_adp_supported(card, IPA_SETADP_SET_SNMP_CONTROL)) && - (!card->options.layer2)) { + IS_LAYER3(card)) return -EOPNOTSUPP; - } + /* skip 4 bytes (data_len struct member) to get req_len */ if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int))) return -EFAULT; @@ -5079,6 +5015,7 @@ static void qeth_core_free_card(struct qeth_card *card) qeth_clean_channel(&card->data); qeth_free_qdio_buffers(card); unregister_service_level(&card->qeth_service_level); + dev_set_drvdata(&card->gdev->dev, NULL); kfree(card); } @@ -5158,7 +5095,7 @@ retriable: qeth_determine_capabilities(card); qeth_init_tokens(card); qeth_init_func_level(card); - rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb); + rc = qeth_idx_activate_channel(card, &card->read, qeth_idx_read_cb); if (rc == -ERESTARTSYS) { QETH_DBF_TEXT(SETUP, 2, "break2"); return rc; @@ -5169,7 +5106,7 @@ retriable: else goto retry; } - rc = qeth_idx_activate_channel(&card->write, qeth_idx_write_cb); + rc = qeth_idx_activate_channel(card, &card->write, qeth_idx_write_cb); if (rc == -ERESTARTSYS) { QETH_DBF_TEXT(SETUP, 2, "break3"); return rc; @@ -5193,13 +5130,14 @@ retriable: if (rc == IPA_RC_LAN_OFFLINE) { dev_warn(&card->gdev->dev, "The LAN is offline\n"); - card->lan_online = 0; + netif_carrier_off(card->dev); } else { rc = -ENODEV; goto out; } - } else - card->lan_online = 1; + } else { + netif_carrier_on(card->dev); + } card->options.ipa4.supported_funcs = 0; card->options.ipa6.supported_funcs = 0; @@ -5593,11 +5531,11 @@ static int qeth_register_dbf_views(void) return 0; } +static DEFINE_MUTEX(qeth_mod_mutex); /* for synchronized module loading */ + 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: @@ -5611,22 +5549,25 @@ int qeth_core_load_discipline(struct qeth_card *card, default: break; } + mutex_unlock(&qeth_mod_mutex); if (!card->discipline) { dev_err(&card->gdev->dev, "There is no kernel module to " "support discipline %d\n", discipline); - rc = -EINVAL; + return -EINVAL; } - mutex_unlock(&qeth_mod_mutex); - return rc; + + card->options.layer = discipline; + return 0; } void qeth_core_free_discipline(struct qeth_card *card) { - if (card->options.layer2) + if (IS_LAYER2(card)) symbol_put(qeth_l2_discipline); else symbol_put(qeth_l3_discipline); + card->options.layer = QETH_DISCIPLINE_UNDETERMINED; card->discipline = NULL; } @@ -5790,7 +5731,6 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) goto err_card; } - dev_set_drvdata(&gdev->dev, card); qeth_setup_card(card); qeth_update_from_chp_desc(card); @@ -5853,7 +5793,6 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev) write_unlock_irq(&qeth_core_card_list.rwlock); free_netdev(card->dev); qeth_core_free_card(card); - dev_set_drvdata(&gdev->dev, NULL); put_device(&gdev->dev); } @@ -6146,7 +6085,7 @@ void qeth_core_get_drvinfo(struct net_device *dev, { struct qeth_card *card = dev->ml_priv; - strlcpy(info->driver, card->options.layer2 ? "qeth_l2" : "qeth_l3", + strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3", sizeof(info->driver)); strlcpy(info->version, "1.0", sizeof(info->version)); strlcpy(info->fw_version, card->info.mcl_level, @@ -6625,9 +6564,7 @@ static int __init qeth_core_init(void) pr_info("loading core functions\n"); INIT_LIST_HEAD(&qeth_core_card_list.list); - INIT_LIST_HEAD(&qeth_dbf_list); rwlock_init(&qeth_core_card_list.rwlock); - mutex_init(&qeth_mod_mutex); qeth_wq = create_singlethread_workqueue("qeth_wq"); if (!qeth_wq) { |