diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 36 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 187 |
2 files changed, 117 insertions, 106 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index f407e3763432..e2fbfff53b50 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -2021,10 +2021,36 @@ void qeth_prepare_control_data(struct qeth_card *card, int len, | |||
2021 | } | 2021 | } |
2022 | EXPORT_SYMBOL_GPL(qeth_prepare_control_data); | 2022 | EXPORT_SYMBOL_GPL(qeth_prepare_control_data); |
2023 | 2023 | ||
2024 | /** | ||
2025 | * qeth_send_control_data() - send control command to the card | ||
2026 | * @card: qeth_card structure pointer | ||
2027 | * @len: size of the command buffer | ||
2028 | * @iob: qeth_cmd_buffer pointer | ||
2029 | * @reply_cb: callback function pointer | ||
2030 | * @cb_card: pointer to the qeth_card structure | ||
2031 | * @cb_reply: pointer to the qeth_reply structure | ||
2032 | * @cb_cmd: pointer to the original iob for non-IPA | ||
2033 | * commands, or to the qeth_ipa_cmd structure | ||
2034 | * for the IPA commands. | ||
2035 | * @reply_param: private pointer passed to the callback | ||
2036 | * | ||
2037 | * Returns the value of the `return_code' field of the response | ||
2038 | * block returned from the hardware, or other error indication. | ||
2039 | * Value of zero indicates successful execution of the command. | ||
2040 | * | ||
2041 | * Callback function gets called one or more times, with cb_cmd | ||
2042 | * pointing to the response returned by the hardware. Callback | ||
2043 | * function must return non-zero if more reply blocks are expected, | ||
2044 | * and zero if the last or only reply block is received. Callback | ||
2045 | * function can get the value of the reply_param pointer from the | ||
2046 | * field 'param' of the structure qeth_reply. | ||
2047 | */ | ||
2048 | |||
2024 | int qeth_send_control_data(struct qeth_card *card, int len, | 2049 | int qeth_send_control_data(struct qeth_card *card, int len, |
2025 | struct qeth_cmd_buffer *iob, | 2050 | struct qeth_cmd_buffer *iob, |
2026 | int (*reply_cb)(struct qeth_card *, struct qeth_reply *, | 2051 | int (*reply_cb)(struct qeth_card *cb_card, |
2027 | unsigned long), | 2052 | struct qeth_reply *cb_reply, |
2053 | unsigned long cb_cmd), | ||
2028 | void *reply_param) | 2054 | void *reply_param) |
2029 | { | 2055 | { |
2030 | int rc; | 2056 | int rc; |
@@ -2932,6 +2958,12 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, | |||
2932 | } | 2958 | } |
2933 | EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd); | 2959 | EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd); |
2934 | 2960 | ||
2961 | /** | ||
2962 | * qeth_send_ipa_cmd() - send an IPA command | ||
2963 | * | ||
2964 | * See qeth_send_control_data() for explanation of the arguments. | ||
2965 | */ | ||
2966 | |||
2935 | int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, | 2967 | int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, |
2936 | int (*reply_cb)(struct qeth_card *, struct qeth_reply*, | 2968 | int (*reply_cb)(struct qeth_card *, struct qeth_reply*, |
2937 | unsigned long), | 2969 | unsigned long), |
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index d02cd1a67943..b7b9d5cbe4d5 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -27,10 +27,7 @@ static int qeth_l2_set_offline(struct ccwgroup_device *); | |||
27 | static int qeth_l2_stop(struct net_device *); | 27 | static int qeth_l2_stop(struct net_device *); |
28 | static int qeth_l2_send_delmac(struct qeth_card *, __u8 *); | 28 | static int qeth_l2_send_delmac(struct qeth_card *, __u8 *); |
29 | static int qeth_l2_send_setdelmac(struct qeth_card *, __u8 *, | 29 | static int qeth_l2_send_setdelmac(struct qeth_card *, __u8 *, |
30 | enum qeth_ipa_cmds, | 30 | enum qeth_ipa_cmds); |
31 | int (*reply_cb) (struct qeth_card *, | ||
32 | struct qeth_reply*, | ||
33 | unsigned long)); | ||
34 | static void qeth_l2_set_multicast_list(struct net_device *); | 31 | static void qeth_l2_set_multicast_list(struct net_device *); |
35 | static int qeth_l2_recover(void *); | 32 | static int qeth_l2_recover(void *); |
36 | static void qeth_bridgeport_query_support(struct qeth_card *card); | 33 | static void qeth_bridgeport_query_support(struct qeth_card *card); |
@@ -130,56 +127,68 @@ static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no) | |||
130 | return ndev; | 127 | return ndev; |
131 | } | 128 | } |
132 | 129 | ||
133 | static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card, | 130 | static int qeth_setdel_makerc(struct qeth_card *card, int retcode) |
134 | struct qeth_reply *reply, | ||
135 | unsigned long data) | ||
136 | { | 131 | { |
137 | struct qeth_ipa_cmd *cmd; | 132 | int rc; |
138 | __u8 *mac; | ||
139 | 133 | ||
140 | QETH_CARD_TEXT(card, 2, "L2Sgmacb"); | 134 | if (retcode) |
141 | cmd = (struct qeth_ipa_cmd *) data; | 135 | QETH_CARD_TEXT_(card, 2, "err%d", retcode); |
142 | mac = &cmd->data.setdelmac.mac[0]; | 136 | switch (retcode) { |
143 | /* MAC already registered, needed in couple/uncouple case */ | 137 | case IPA_RC_SUCCESS: |
144 | if (cmd->hdr.return_code == IPA_RC_L2_DUP_MAC) { | 138 | rc = 0; |
145 | QETH_DBF_MESSAGE(2, "Group MAC %pM already existing on %s \n", | 139 | break; |
146 | mac, QETH_CARD_IFNAME(card)); | 140 | case IPA_RC_L2_UNSUPPORTED_CMD: |
147 | cmd->hdr.return_code = 0; | 141 | rc = -ENOSYS; |
142 | break; | ||
143 | case IPA_RC_L2_ADDR_TABLE_FULL: | ||
144 | rc = -ENOSPC; | ||
145 | break; | ||
146 | case IPA_RC_L2_DUP_MAC: | ||
147 | case IPA_RC_L2_DUP_LAYER3_MAC: | ||
148 | rc = -EEXIST; | ||
149 | break; | ||
150 | case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: | ||
151 | case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: | ||
152 | rc = -EPERM; | ||
153 | break; | ||
154 | case IPA_RC_L2_MAC_NOT_FOUND: | ||
155 | rc = -ENOENT; | ||
156 | break; | ||
157 | default: | ||
158 | rc = -EIO; | ||
159 | break; | ||
148 | } | 160 | } |
149 | if (cmd->hdr.return_code) | 161 | return rc; |
150 | QETH_DBF_MESSAGE(2, "Could not set group MAC %pM on %s: %x\n", | ||
151 | mac, QETH_CARD_IFNAME(card), cmd->hdr.return_code); | ||
152 | return 0; | ||
153 | } | 162 | } |
154 | 163 | ||
155 | static int qeth_l2_send_setgroupmac(struct qeth_card *card, __u8 *mac) | 164 | static int qeth_l2_send_setgroupmac(struct qeth_card *card, __u8 *mac) |
156 | { | 165 | { |
157 | QETH_CARD_TEXT(card, 2, "L2Sgmac"); | 166 | int rc; |
158 | return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETGMAC, | ||
159 | qeth_l2_send_setgroupmac_cb); | ||
160 | } | ||
161 | |||
162 | static int qeth_l2_send_delgroupmac_cb(struct qeth_card *card, | ||
163 | struct qeth_reply *reply, | ||
164 | unsigned long data) | ||
165 | { | ||
166 | struct qeth_ipa_cmd *cmd; | ||
167 | __u8 *mac; | ||
168 | 167 | ||
169 | QETH_CARD_TEXT(card, 2, "L2Dgmacb"); | 168 | QETH_CARD_TEXT(card, 2, "L2Sgmac"); |
170 | cmd = (struct qeth_ipa_cmd *) data; | 169 | rc = qeth_setdel_makerc(card, qeth_l2_send_setdelmac(card, mac, |
171 | mac = &cmd->data.setdelmac.mac[0]; | 170 | IPA_CMD_SETGMAC)); |
172 | if (cmd->hdr.return_code) | 171 | if (rc == -EEXIST) |
173 | QETH_DBF_MESSAGE(2, "Could not delete group MAC %pM on %s: %x\n", | 172 | QETH_DBF_MESSAGE(2, "Group MAC %pM already existing on %s\n", |
174 | mac, QETH_CARD_IFNAME(card), cmd->hdr.return_code); | 173 | mac, QETH_CARD_IFNAME(card)); |
175 | return 0; | 174 | else if (rc) |
175 | QETH_DBF_MESSAGE(2, "Could not set group MAC %pM on %s: %d\n", | ||
176 | mac, QETH_CARD_IFNAME(card), rc); | ||
177 | return rc; | ||
176 | } | 178 | } |
177 | 179 | ||
178 | static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac) | 180 | static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac) |
179 | { | 181 | { |
182 | int rc; | ||
183 | |||
180 | QETH_CARD_TEXT(card, 2, "L2Dgmac"); | 184 | QETH_CARD_TEXT(card, 2, "L2Dgmac"); |
181 | return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELGMAC, | 185 | rc = qeth_setdel_makerc(card, qeth_l2_send_setdelmac(card, mac, |
182 | qeth_l2_send_delgroupmac_cb); | 186 | IPA_CMD_DELGMAC)); |
187 | if (rc) | ||
188 | QETH_DBF_MESSAGE(2, | ||
189 | "Could not delete group MAC %pM on %s: %d\n", | ||
190 | mac, QETH_CARD_IFNAME(card), rc); | ||
191 | return rc; | ||
183 | } | 192 | } |
184 | 193 | ||
185 | static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac) | 194 | static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac) |
@@ -197,10 +206,11 @@ static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac) | |||
197 | mc->is_vmac = vmac; | 206 | mc->is_vmac = vmac; |
198 | 207 | ||
199 | if (vmac) { | 208 | if (vmac) { |
200 | rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC, | 209 | rc = qeth_setdel_makerc(card, |
201 | NULL); | 210 | qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC)); |
202 | } else { | 211 | } else { |
203 | rc = qeth_l2_send_setgroupmac(card, mac); | 212 | rc = qeth_setdel_makerc(card, |
213 | qeth_l2_send_setgroupmac(card, mac)); | ||
204 | } | 214 | } |
205 | 215 | ||
206 | if (!rc) | 216 | if (!rc) |
@@ -218,7 +228,7 @@ static void qeth_l2_del_all_mc(struct qeth_card *card, int del) | |||
218 | if (del) { | 228 | if (del) { |
219 | if (mc->is_vmac) | 229 | if (mc->is_vmac) |
220 | qeth_l2_send_setdelmac(card, mc->mc_addr, | 230 | qeth_l2_send_setdelmac(card, mc->mc_addr, |
221 | IPA_CMD_DELVMAC, NULL); | 231 | IPA_CMD_DELVMAC); |
222 | else | 232 | else |
223 | qeth_l2_send_delgroupmac(card, mc->mc_addr); | 233 | qeth_l2_send_delgroupmac(card, mc->mc_addr); |
224 | } | 234 | } |
@@ -539,10 +549,7 @@ out: | |||
539 | } | 549 | } |
540 | 550 | ||
541 | static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, | 551 | static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, |
542 | enum qeth_ipa_cmds ipacmd, | 552 | enum qeth_ipa_cmds ipacmd) |
543 | int (*reply_cb) (struct qeth_card *, | ||
544 | struct qeth_reply*, | ||
545 | unsigned long)) | ||
546 | { | 553 | { |
547 | struct qeth_ipa_cmd *cmd; | 554 | struct qeth_ipa_cmd *cmd; |
548 | struct qeth_cmd_buffer *iob; | 555 | struct qeth_cmd_buffer *iob; |
@@ -552,78 +559,50 @@ static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, | |||
552 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | 559 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); |
553 | cmd->data.setdelmac.mac_length = OSA_ADDR_LEN; | 560 | cmd->data.setdelmac.mac_length = OSA_ADDR_LEN; |
554 | memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN); | 561 | memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN); |
555 | return qeth_send_ipa_cmd(card, iob, reply_cb, NULL); | 562 | return qeth_send_ipa_cmd(card, iob, NULL, NULL); |
556 | } | 563 | } |
557 | 564 | ||
558 | static int qeth_l2_send_setmac_cb(struct qeth_card *card, | 565 | static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac) |
559 | struct qeth_reply *reply, | ||
560 | unsigned long data) | ||
561 | { | 566 | { |
562 | struct qeth_ipa_cmd *cmd; | 567 | int rc; |
563 | 568 | ||
564 | QETH_CARD_TEXT(card, 2, "L2Smaccb"); | 569 | QETH_CARD_TEXT(card, 2, "L2Setmac"); |
565 | cmd = (struct qeth_ipa_cmd *) data; | 570 | rc = qeth_setdel_makerc(card, qeth_l2_send_setdelmac(card, mac, |
566 | if (cmd->hdr.return_code) { | 571 | IPA_CMD_SETVMAC)); |
567 | QETH_CARD_TEXT_(card, 2, "L2er%x", cmd->hdr.return_code); | 572 | if (rc == 0) { |
573 | card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; | ||
574 | memcpy(card->dev->dev_addr, mac, OSA_ADDR_LEN); | ||
575 | dev_info(&card->gdev->dev, | ||
576 | "MAC address %pM successfully registered on device %s\n", | ||
577 | card->dev->dev_addr, card->dev->name); | ||
578 | } else { | ||
568 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; | 579 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; |
569 | switch (cmd->hdr.return_code) { | 580 | switch (rc) { |
570 | case IPA_RC_L2_DUP_MAC: | 581 | case -EEXIST: |
571 | case IPA_RC_L2_DUP_LAYER3_MAC: | ||
572 | dev_warn(&card->gdev->dev, | 582 | dev_warn(&card->gdev->dev, |
573 | "MAC address %pM already exists\n", | 583 | "MAC address %pM already exists\n", mac); |
574 | cmd->data.setdelmac.mac); | ||
575 | break; | 584 | break; |
576 | case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: | 585 | case -EPERM: |
577 | case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: | ||
578 | dev_warn(&card->gdev->dev, | 586 | dev_warn(&card->gdev->dev, |
579 | "MAC address %pM is not authorized\n", | 587 | "MAC address %pM is not authorized\n", mac); |
580 | cmd->data.setdelmac.mac); | ||
581 | break; | ||
582 | default: | ||
583 | break; | 588 | break; |
584 | } | 589 | } |
585 | } else { | ||
586 | card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; | ||
587 | memcpy(card->dev->dev_addr, cmd->data.setdelmac.mac, | ||
588 | OSA_ADDR_LEN); | ||
589 | dev_info(&card->gdev->dev, | ||
590 | "MAC address %pM successfully registered on device %s\n", | ||
591 | card->dev->dev_addr, card->dev->name); | ||
592 | } | 590 | } |
593 | return 0; | 591 | return rc; |
594 | } | ||
595 | |||
596 | static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac) | ||
597 | { | ||
598 | QETH_CARD_TEXT(card, 2, "L2Setmac"); | ||
599 | return qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC, | ||
600 | qeth_l2_send_setmac_cb); | ||
601 | } | ||
602 | |||
603 | static int qeth_l2_send_delmac_cb(struct qeth_card *card, | ||
604 | struct qeth_reply *reply, | ||
605 | unsigned long data) | ||
606 | { | ||
607 | struct qeth_ipa_cmd *cmd; | ||
608 | |||
609 | QETH_CARD_TEXT(card, 2, "L2Dmaccb"); | ||
610 | cmd = (struct qeth_ipa_cmd *) data; | ||
611 | if (cmd->hdr.return_code) { | ||
612 | QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code); | ||
613 | return 0; | ||
614 | } | ||
615 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; | ||
616 | |||
617 | return 0; | ||
618 | } | 592 | } |
619 | 593 | ||
620 | static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac) | 594 | static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac) |
621 | { | 595 | { |
596 | int rc; | ||
597 | |||
622 | QETH_CARD_TEXT(card, 2, "L2Delmac"); | 598 | QETH_CARD_TEXT(card, 2, "L2Delmac"); |
623 | if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) | 599 | if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) |
624 | return 0; | 600 | return 0; |
625 | return qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC, | 601 | rc = qeth_setdel_makerc(card, qeth_l2_send_setdelmac(card, mac, |
626 | qeth_l2_send_delmac_cb); | 602 | IPA_CMD_DELVMAC)); |
603 | if (rc == 0) | ||
604 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; | ||
605 | return rc; | ||
627 | } | 606 | } |
628 | 607 | ||
629 | static int qeth_l2_request_initial_mac(struct qeth_card *card) | 608 | static int qeth_l2_request_initial_mac(struct qeth_card *card) |
@@ -687,7 +666,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) | |||
687 | return -ERESTARTSYS; | 666 | return -ERESTARTSYS; |
688 | } | 667 | } |
689 | rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]); | 668 | rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]); |
690 | if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND)) | 669 | if (!rc || (rc == -ENOENT)) |
691 | rc = qeth_l2_send_setmac(card, addr->sa_data); | 670 | rc = qeth_l2_send_setmac(card, addr->sa_data); |
692 | return rc ? -EINVAL : 0; | 671 | return rc ? -EINVAL : 0; |
693 | } | 672 | } |