aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_l3_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net/qeth_l3_main.c')
-rw-r--r--drivers/s390/net/qeth_l3_main.c123
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
70static 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
70static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len) 88static 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
123inline int
124qeth_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
131static struct qeth_ipaddr *
132qeth_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
151int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) 141int 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,
2450static int qeth_l3_get_elements_no_tso(struct qeth_card *card, 2432static 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,