Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[muen/linux.git] / drivers / s390 / net / qeth_core_main.c
index 5f10e3a..04fefa5 100644 (file)
@@ -527,8 +527,7 @@ static inline int qeth_is_cq(struct qeth_card *card, unsigned int queue)
            queue == card->qdio.no_in_queues - 1;
 }
 
-
-static int qeth_issue_next_read(struct qeth_card *card)
+static int __qeth_issue_next_read(struct qeth_card *card)
 {
        int rc;
        struct qeth_cmd_buffer *iob;
@@ -559,6 +558,17 @@ static int qeth_issue_next_read(struct qeth_card *card)
        return rc;
 }
 
+static int qeth_issue_next_read(struct qeth_card *card)
+{
+       int ret;
+
+       spin_lock_irq(get_ccwdev_lock(CARD_RDEV(card)));
+       ret = __qeth_issue_next_read(card);
+       spin_unlock_irq(get_ccwdev_lock(CARD_RDEV(card)));
+
+       return ret;
+}
+
 static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
 {
        struct qeth_reply *reply;
@@ -708,11 +718,8 @@ static int qeth_check_idx_response(struct qeth_card *card,
 
        QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN);
        if ((buffer[2] & 0xc0) == 0xc0) {
-               QETH_DBF_MESSAGE(2, "received an IDX TERMINATE "
-                          "with cause code 0x%02x%s\n",
-                          buffer[4],
-                          ((buffer[4] == 0x22) ?
-                           " -- try another portname" : ""));
+               QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#02x\n",
+                                buffer[4]);
                QETH_CARD_TEXT(card, 2, "ckidxres");
                QETH_CARD_TEXT(card, 2, " idxterm");
                QETH_CARD_TEXT_(card, 2, "  rc%d", -EIO);
@@ -960,7 +967,7 @@ void qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
        spin_lock_irqsave(&card->thread_mask_lock, flags);
        card->thread_running_mask &= ~thread;
        spin_unlock_irqrestore(&card->thread_mask_lock, flags);
-       wake_up(&card->wait_q);
+       wake_up_all(&card->wait_q);
 }
 EXPORT_SYMBOL_GPL(qeth_clear_thread_running_bit);
 
@@ -1164,6 +1171,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
                }
                rc = qeth_get_problem(cdev, irb);
                if (rc) {
+                       card->read_or_write_problem = 1;
                        qeth_clear_ipacmd_list(card);
                        qeth_schedule_recovery(card);
                        goto out;
@@ -1182,7 +1190,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
                return;
        if (channel == &card->read &&
            channel->state == CH_STATE_UP)
-               qeth_issue_next_read(card);
+               __qeth_issue_next_read(card);
 
        iob = channel->iob;
        index = channel->buf_no;
@@ -2134,24 +2142,25 @@ int qeth_send_control_data(struct qeth_card *card, int len,
        }
        reply->callback = reply_cb;
        reply->param = reply_param;
-       if (card->state == CARD_STATE_DOWN)
-               reply->seqno = QETH_IDX_COMMAND_SEQNO;
-       else
-               reply->seqno = card->seqno.ipa++;
+
        init_waitqueue_head(&reply->wait_q);
-       spin_lock_irqsave(&card->lock, flags);
-       list_add_tail(&reply->list, &card->cmd_waiter_list);
-       spin_unlock_irqrestore(&card->lock, flags);
 
        while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
-       qeth_prepare_control_data(card, len, iob);
 
        if (IS_IPA(iob->data)) {
                cmd = __ipa_cmd(iob);
+               cmd->hdr.seqno = card->seqno.ipa++;
+               reply->seqno = cmd->hdr.seqno;
                event_timeout = QETH_IPA_TIMEOUT;
        } else {
+               reply->seqno = QETH_IDX_COMMAND_SEQNO;
                event_timeout = QETH_TIMEOUT;
        }
+       qeth_prepare_control_data(card, len, iob);
+
+       spin_lock_irqsave(&card->lock, flags);
+       list_add_tail(&reply->list, &card->cmd_waiter_list);
+       spin_unlock_irqrestore(&card->lock, flags);
 
        timeout = jiffies + event_timeout;
 
@@ -2837,7 +2846,8 @@ static int qeth_init_input_buffer(struct qeth_card *card,
        int i;
 
        if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) {
-               buf->rx_skb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN);
+               buf->rx_skb = netdev_alloc_skb(card->dev,
+                                              QETH_RX_PULL_LEN + ETH_HLEN);
                if (!buf->rx_skb)
                        return 1;
        }
@@ -2874,8 +2884,8 @@ int qeth_init_qdio_queues(struct qeth_card *card)
        QETH_DBF_TEXT(SETUP, 2, "initqdqs");
 
        /* inbound queue */
-       qdio_reset_buffers(card->qdio.in_q->qdio_bufs,
-                          QDIO_MAX_BUFFERS_PER_Q);
+       qdio_reset_buffers(card->qdio.in_q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
+       memset(&card->rx, 0, sizeof(struct qeth_rx));
        qeth_initialize_working_pool_list(card);
        /*give only as many buffers to hardware as we have buffer pool entries*/
        for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
@@ -2933,7 +2943,7 @@ static void qeth_fill_ipacmd_header(struct qeth_card *card,
        memset(cmd, 0, sizeof(struct qeth_ipa_cmd));
        cmd->hdr.command = command;
        cmd->hdr.initiator = IPA_CMD_INITIATOR_HOST;
-       cmd->hdr.seqno = card->seqno.ipa;
+       /* 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->info.portno;
        if (card->options.layer2)
@@ -2950,12 +2960,10 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
                enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
 {
        struct qeth_cmd_buffer *iob;
-       struct qeth_ipa_cmd *cmd;
 
        iob = qeth_get_buffer(&card->write);
        if (iob) {
-               cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-               qeth_fill_ipacmd_header(card, cmd, ipacmd, prot);
+               qeth_fill_ipacmd_header(card, __ipa_cmd(iob), ipacmd, prot);
        } else {
                dev_warn(&card->gdev->dev,
                         "The qeth driver ran out of channel command buffers\n");
@@ -3066,7 +3074,7 @@ static struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *card,
        iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETADAPTERPARMS,
                                     QETH_PROT_IPV4);
        if (iob) {
-               cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+               cmd = __ipa_cmd(iob);
                cmd->data.setadapterparms.hdr.cmdlength = cmdlen;
                cmd->data.setadapterparms.hdr.command_code = command;
                cmd->data.setadapterparms.hdr.used_total = 1;
@@ -3208,7 +3216,7 @@ static int qeth_query_setdiagass(struct qeth_card *card)
        iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
        if (!iob)
                return -ENOMEM;
-       cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+       cmd = __ipa_cmd(iob);
        cmd->data.diagass.subcmd_len = 16;
        cmd->data.diagass.subcmd = QETH_DIAGS_CMD_QUERY;
        return qeth_send_ipa_cmd(card, iob, qeth_query_setdiagass_cb, NULL);
@@ -3261,7 +3269,7 @@ int qeth_hw_trap(struct qeth_card *card, enum qeth_diags_trap_action action)
        iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
        if (!iob)
                return -ENOMEM;
-       cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+       cmd = __ipa_cmd(iob);
        cmd->data.diagass.subcmd_len = 80;
        cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRAP;
        cmd->data.diagass.type = 1;
@@ -3898,10 +3906,12 @@ EXPORT_SYMBOL_GPL(qeth_get_elements_for_frags);
 int qeth_get_elements_no(struct qeth_card *card,
                     struct sk_buff *skb, int extra_elems, int data_offset)
 {
-       int elements = qeth_get_elements_for_range(
-                               (addr_t)skb->data + data_offset,
-                               (addr_t)skb->data + skb_headlen(skb)) +
-                       qeth_get_elements_for_frags(skb);
+       addr_t end = (addr_t)skb->data + skb_headlen(skb);
+       int elements = qeth_get_elements_for_frags(skb);
+       addr_t start = (addr_t)skb->data + data_offset;
+
+       if (start != end)
+               elements += qeth_get_elements_for_range(start, end);
 
        if ((elements + extra_elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
                QETH_DBF_MESSAGE(2, "Invalid size of IP packet "
@@ -4237,7 +4247,7 @@ void qeth_setadp_promisc_mode(struct qeth_card *card)
                        sizeof(struct qeth_ipacmd_setadpparms_hdr) + 8);
        if (!iob)
                return;
-       cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
+       cmd = __ipa_cmd(iob);
        cmd->data.setadapterparms.data.mode = mode;
        qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
 }
@@ -4304,7 +4314,7 @@ int qeth_setadpparms_change_macaddr(struct qeth_card *card)
                                   sizeof(struct qeth_change_addr));
        if (!iob)
                return -ENOMEM;
-       cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+       cmd = __ipa_cmd(iob);
        cmd->data.setadapterparms.data.change_addr.cmd = CHANGE_ADDR_READ_MAC;
        cmd->data.setadapterparms.data.change_addr.addr_size = ETH_ALEN;
        ether_addr_copy(cmd->data.setadapterparms.data.change_addr.addr,
@@ -4419,7 +4429,7 @@ static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
                                   sizeof(struct qeth_set_access_ctrl));
        if (!iob)
                return -ENOMEM;
-       cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+       cmd = __ipa_cmd(iob);
        access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
        access_ctrl_req->subcmd_code = isolation;
 
@@ -4665,7 +4675,7 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
                rc = -ENOMEM;
                goto out;
        }
-       cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+       cmd = __ipa_cmd(iob);
        memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
        rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
                                    qeth_snmp_command_cb, (void *)&qinfo);
@@ -4750,7 +4760,7 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
                rc = -ENOMEM;
                goto out_free;
        }
-       cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+       cmd = __ipa_cmd(iob);
        oat_req = &cmd->data.setadapterparms.data.query_oat;
        oat_req->subcmd_code = oat_data.command;
 
@@ -5084,8 +5094,6 @@ static void qeth_core_free_card(struct qeth_card *card)
        QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
        qeth_clean_channel(&card->read);
        qeth_clean_channel(&card->write);
-       if (card->dev)
-               free_netdev(card->dev);
        qeth_free_qdio_buffers(card);
        unregister_service_level(&card->qeth_service_level);
        kfree(card);
@@ -5327,7 +5335,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
        } else {
                unsigned int linear = (use_rx_sg) ? QETH_RX_PULL_LEN : skb_len;
 
-               skb = dev_alloc_skb(linear + headroom);
+               skb = napi_alloc_skb(&card->napi, linear + headroom);
        }
        if (!skb)
                goto no_mem;
@@ -5491,7 +5499,7 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
        iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETASSPARMS, prot);
 
        if (iob) {
-               cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+               cmd = __ipa_cmd(iob);
                cmd->data.setassparms.hdr.assist_no = ipa_func;
                cmd->data.setassparms.hdr.length = 8 + len;
                cmd->data.setassparms.hdr.command_code = cmd_code;
@@ -5514,7 +5522,7 @@ int qeth_send_setassparms(struct qeth_card *card,
 
        QETH_CARD_TEXT(card, 4, "sendassp");
 
-       cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+       cmd = __ipa_cmd(iob);
        if (len <= sizeof(__u32))
                cmd->data.setassparms.data.flags_32bit = (__u32) data;
        else   /* (len > sizeof(__u32)) */