diff options
Diffstat (limited to 'drivers/s390/net/qeth_l3_main.c')
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 123 |
1 files changed, 53 insertions, 70 deletions
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index b0c888e86cd4..962a04b68dd2 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -67,6 +67,24 @@ void qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const __u8 *addr, | |||
67 | qeth_l3_ipaddr6_to_string(addr, buf); | 67 | qeth_l3_ipaddr6_to_string(addr, buf); |
68 | } | 68 | } |
69 | 69 | ||
70 | static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card, | ||
71 | struct qeth_ipaddr *query) | ||
72 | { | ||
73 | u64 key = qeth_l3_ipaddr_hash(query); | ||
74 | struct qeth_ipaddr *addr; | ||
75 | |||
76 | if (query->is_multicast) { | ||
77 | hash_for_each_possible(card->ip_mc_htable, addr, hnode, key) | ||
78 | if (qeth_l3_addr_match_ip(addr, query)) | ||
79 | return addr; | ||
80 | } else { | ||
81 | hash_for_each_possible(card->ip_htable, addr, hnode, key) | ||
82 | if (qeth_l3_addr_match_ip(addr, query)) | ||
83 | return addr; | ||
84 | } | ||
85 | return NULL; | ||
86 | } | ||
87 | |||
70 | static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len) | 88 | static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len) |
71 | { | 89 | { |
72 | int i, j; | 90 | int i, j; |
@@ -120,34 +138,6 @@ static bool qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, | |||
120 | return rc; | 138 | return rc; |
121 | } | 139 | } |
122 | 140 | ||
123 | inline int | ||
124 | qeth_l3_ipaddrs_is_equal(struct qeth_ipaddr *addr1, struct qeth_ipaddr *addr2) | ||
125 | { | ||
126 | return addr1->proto == addr2->proto && | ||
127 | !memcmp(&addr1->u, &addr2->u, sizeof(addr1->u)) && | ||
128 | ether_addr_equal_64bits(addr1->mac, addr2->mac); | ||
129 | } | ||
130 | |||
131 | static struct qeth_ipaddr * | ||
132 | qeth_l3_ip_from_hash(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) | ||
133 | { | ||
134 | struct qeth_ipaddr *addr; | ||
135 | |||
136 | if (tmp_addr->is_multicast) { | ||
137 | hash_for_each_possible(card->ip_mc_htable, addr, | ||
138 | hnode, qeth_l3_ipaddr_hash(tmp_addr)) | ||
139 | if (qeth_l3_ipaddrs_is_equal(tmp_addr, addr)) | ||
140 | return addr; | ||
141 | } else { | ||
142 | hash_for_each_possible(card->ip_htable, addr, | ||
143 | hnode, qeth_l3_ipaddr_hash(tmp_addr)) | ||
144 | if (qeth_l3_ipaddrs_is_equal(tmp_addr, addr)) | ||
145 | return addr; | ||
146 | } | ||
147 | |||
148 | return NULL; | ||
149 | } | ||
150 | |||
151 | int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) | 141 | int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) |
152 | { | 142 | { |
153 | int rc = 0; | 143 | int rc = 0; |
@@ -162,23 +152,18 @@ int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) | |||
162 | QETH_CARD_HEX(card, 4, ((char *)&tmp_addr->u.a6.addr) + 8, 8); | 152 | QETH_CARD_HEX(card, 4, ((char *)&tmp_addr->u.a6.addr) + 8, 8); |
163 | } | 153 | } |
164 | 154 | ||
165 | addr = qeth_l3_ip_from_hash(card, tmp_addr); | 155 | addr = qeth_l3_find_addr_by_ip(card, tmp_addr); |
166 | if (!addr) | 156 | if (!addr || !qeth_l3_addr_match_all(addr, tmp_addr)) |
167 | return -ENOENT; | 157 | return -ENOENT; |
168 | 158 | ||
169 | addr->ref_counter--; | 159 | addr->ref_counter--; |
170 | if (addr->ref_counter > 0 && (addr->type == QETH_IP_TYPE_NORMAL || | 160 | if (addr->type == QETH_IP_TYPE_NORMAL && addr->ref_counter > 0) |
171 | addr->type == QETH_IP_TYPE_RXIP)) | ||
172 | return rc; | 161 | return rc; |
173 | if (addr->in_progress) | 162 | if (addr->in_progress) |
174 | return -EINPROGRESS; | 163 | return -EINPROGRESS; |
175 | 164 | ||
176 | if (!qeth_card_hw_is_reachable(card)) { | 165 | if (qeth_card_hw_is_reachable(card)) |
177 | addr->disp_flag = QETH_DISP_ADDR_DELETE; | 166 | rc = qeth_l3_deregister_addr_entry(card, addr); |
178 | return 0; | ||
179 | } | ||
180 | |||
181 | rc = qeth_l3_deregister_addr_entry(card, addr); | ||
182 | 167 | ||
183 | hash_del(&addr->hnode); | 168 | hash_del(&addr->hnode); |
184 | kfree(addr); | 169 | kfree(addr); |
@@ -190,6 +175,7 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) | |||
190 | { | 175 | { |
191 | int rc = 0; | 176 | int rc = 0; |
192 | struct qeth_ipaddr *addr; | 177 | struct qeth_ipaddr *addr; |
178 | char buf[40]; | ||
193 | 179 | ||
194 | QETH_CARD_TEXT(card, 4, "addip"); | 180 | QETH_CARD_TEXT(card, 4, "addip"); |
195 | 181 | ||
@@ -200,8 +186,20 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) | |||
200 | QETH_CARD_HEX(card, 4, ((char *)&tmp_addr->u.a6.addr) + 8, 8); | 186 | QETH_CARD_HEX(card, 4, ((char *)&tmp_addr->u.a6.addr) + 8, 8); |
201 | } | 187 | } |
202 | 188 | ||
203 | addr = qeth_l3_ip_from_hash(card, tmp_addr); | 189 | addr = qeth_l3_find_addr_by_ip(card, tmp_addr); |
204 | if (!addr) { | 190 | if (addr) { |
191 | if (tmp_addr->type != QETH_IP_TYPE_NORMAL) | ||
192 | return -EADDRINUSE; | ||
193 | if (qeth_l3_addr_match_all(addr, tmp_addr)) { | ||
194 | addr->ref_counter++; | ||
195 | return 0; | ||
196 | } | ||
197 | qeth_l3_ipaddr_to_string(tmp_addr->proto, (u8 *)&tmp_addr->u, | ||
198 | buf); | ||
199 | dev_warn(&card->gdev->dev, | ||
200 | "Registering IP address %s failed\n", buf); | ||
201 | return -EADDRINUSE; | ||
202 | } else { | ||
205 | addr = qeth_l3_get_addr_buffer(tmp_addr->proto); | 203 | addr = qeth_l3_get_addr_buffer(tmp_addr->proto); |
206 | if (!addr) | 204 | if (!addr) |
207 | return -ENOMEM; | 205 | return -ENOMEM; |
@@ -241,19 +239,15 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) | |||
241 | (rc == IPA_RC_LAN_OFFLINE)) { | 239 | (rc == IPA_RC_LAN_OFFLINE)) { |
242 | addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING; | 240 | addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING; |
243 | if (addr->ref_counter < 1) { | 241 | if (addr->ref_counter < 1) { |
244 | qeth_l3_delete_ip(card, addr); | 242 | qeth_l3_deregister_addr_entry(card, addr); |
243 | hash_del(&addr->hnode); | ||
245 | kfree(addr); | 244 | kfree(addr); |
246 | } | 245 | } |
247 | } else { | 246 | } else { |
248 | hash_del(&addr->hnode); | 247 | hash_del(&addr->hnode); |
249 | kfree(addr); | 248 | kfree(addr); |
250 | } | 249 | } |
251 | } else { | ||
252 | if (addr->type == QETH_IP_TYPE_NORMAL || | ||
253 | addr->type == QETH_IP_TYPE_RXIP) | ||
254 | addr->ref_counter++; | ||
255 | } | 250 | } |
256 | |||
257 | return rc; | 251 | return rc; |
258 | } | 252 | } |
259 | 253 | ||
@@ -321,11 +315,7 @@ static void qeth_l3_recover_ip(struct qeth_card *card) | |||
321 | spin_lock_bh(&card->ip_lock); | 315 | spin_lock_bh(&card->ip_lock); |
322 | 316 | ||
323 | hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) { | 317 | hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) { |
324 | if (addr->disp_flag == QETH_DISP_ADDR_DELETE) { | 318 | if (addr->disp_flag == QETH_DISP_ADDR_ADD) { |
325 | qeth_l3_deregister_addr_entry(card, addr); | ||
326 | hash_del(&addr->hnode); | ||
327 | kfree(addr); | ||
328 | } else if (addr->disp_flag == QETH_DISP_ADDR_ADD) { | ||
329 | if (addr->proto == QETH_PROT_IPV4) { | 319 | if (addr->proto == QETH_PROT_IPV4) { |
330 | addr->in_progress = 1; | 320 | addr->in_progress = 1; |
331 | spin_unlock_bh(&card->ip_lock); | 321 | spin_unlock_bh(&card->ip_lock); |
@@ -643,12 +633,7 @@ int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto, | |||
643 | return -ENOMEM; | 633 | return -ENOMEM; |
644 | 634 | ||
645 | spin_lock_bh(&card->ip_lock); | 635 | spin_lock_bh(&card->ip_lock); |
646 | 636 | rc = qeth_l3_add_ip(card, ipaddr); | |
647 | if (qeth_l3_ip_from_hash(card, ipaddr)) | ||
648 | rc = -EEXIST; | ||
649 | else | ||
650 | rc = qeth_l3_add_ip(card, ipaddr); | ||
651 | |||
652 | spin_unlock_bh(&card->ip_lock); | 637 | spin_unlock_bh(&card->ip_lock); |
653 | 638 | ||
654 | kfree(ipaddr); | 639 | kfree(ipaddr); |
@@ -713,12 +698,7 @@ int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto, | |||
713 | return -ENOMEM; | 698 | return -ENOMEM; |
714 | 699 | ||
715 | spin_lock_bh(&card->ip_lock); | 700 | spin_lock_bh(&card->ip_lock); |
716 | 701 | rc = qeth_l3_add_ip(card, ipaddr); | |
717 | if (qeth_l3_ip_from_hash(card, ipaddr)) | ||
718 | rc = -EEXIST; | ||
719 | else | ||
720 | rc = qeth_l3_add_ip(card, ipaddr); | ||
721 | |||
722 | spin_unlock_bh(&card->ip_lock); | 702 | spin_unlock_bh(&card->ip_lock); |
723 | 703 | ||
724 | kfree(ipaddr); | 704 | kfree(ipaddr); |
@@ -1239,8 +1219,9 @@ qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev) | |||
1239 | tmp->u.a4.addr = be32_to_cpu(im4->multiaddr); | 1219 | tmp->u.a4.addr = be32_to_cpu(im4->multiaddr); |
1240 | tmp->is_multicast = 1; | 1220 | tmp->is_multicast = 1; |
1241 | 1221 | ||
1242 | ipm = qeth_l3_ip_from_hash(card, tmp); | 1222 | ipm = qeth_l3_find_addr_by_ip(card, tmp); |
1243 | if (ipm) { | 1223 | if (ipm) { |
1224 | /* for mcast, by-IP match means full match */ | ||
1244 | ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING; | 1225 | ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING; |
1245 | } else { | 1226 | } else { |
1246 | ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); | 1227 | ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); |
@@ -1319,8 +1300,9 @@ static void qeth_l3_add_mc6_to_hash(struct qeth_card *card, | |||
1319 | sizeof(struct in6_addr)); | 1300 | sizeof(struct in6_addr)); |
1320 | tmp->is_multicast = 1; | 1301 | tmp->is_multicast = 1; |
1321 | 1302 | ||
1322 | ipm = qeth_l3_ip_from_hash(card, tmp); | 1303 | ipm = qeth_l3_find_addr_by_ip(card, tmp); |
1323 | if (ipm) { | 1304 | if (ipm) { |
1305 | /* for mcast, by-IP match means full match */ | ||
1324 | ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING; | 1306 | ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING; |
1325 | continue; | 1307 | continue; |
1326 | } | 1308 | } |
@@ -2450,11 +2432,12 @@ static void qeth_tso_fill_header(struct qeth_card *card, | |||
2450 | static int qeth_l3_get_elements_no_tso(struct qeth_card *card, | 2432 | static int qeth_l3_get_elements_no_tso(struct qeth_card *card, |
2451 | struct sk_buff *skb, int extra_elems) | 2433 | struct sk_buff *skb, int extra_elems) |
2452 | { | 2434 | { |
2453 | addr_t tcpdptr = (addr_t)tcp_hdr(skb) + tcp_hdrlen(skb); | 2435 | addr_t start = (addr_t)tcp_hdr(skb) + tcp_hdrlen(skb); |
2454 | int elements = qeth_get_elements_for_range( | 2436 | addr_t end = (addr_t)skb->data + skb_headlen(skb); |
2455 | tcpdptr, | 2437 | int elements = qeth_get_elements_for_frags(skb); |
2456 | (addr_t)skb->data + skb_headlen(skb)) + | 2438 | |
2457 | qeth_get_elements_for_frags(skb); | 2439 | if (start != end) |
2440 | elements += qeth_get_elements_for_range(start, end); | ||
2458 | 2441 | ||
2459 | if ((elements + extra_elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { | 2442 | if ((elements + extra_elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { |
2460 | QETH_DBF_MESSAGE(2, | 2443 | QETH_DBF_MESSAGE(2, |