diff options
| -rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 217 | ||||
| -rw-r--r-- | drivers/scsi/fcoe/fcoe.h | 44 | ||||
| -rw-r--r-- | drivers/scsi/fcoe/fcoe_transport.c | 200 | ||||
| -rw-r--r-- | include/scsi/libfcoe.h | 51 |
4 files changed, 275 insertions, 237 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 46c57e5755ae..495456fe4520 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
| @@ -75,7 +75,6 @@ static int fcoe_xmit(struct fc_lport *, struct fc_frame *); | |||
| 75 | static int fcoe_rcv(struct sk_buff *, struct net_device *, | 75 | static int fcoe_rcv(struct sk_buff *, struct net_device *, |
| 76 | struct packet_type *, struct net_device *); | 76 | struct packet_type *, struct net_device *); |
| 77 | static int fcoe_percpu_receive_thread(void *); | 77 | static int fcoe_percpu_receive_thread(void *); |
| 78 | static void fcoe_clean_pending_queue(struct fc_lport *); | ||
| 79 | static void fcoe_percpu_clean(struct fc_lport *); | 78 | static void fcoe_percpu_clean(struct fc_lport *); |
| 80 | static int fcoe_link_speed_update(struct fc_lport *); | 79 | static int fcoe_link_speed_update(struct fc_lport *); |
| 81 | static int fcoe_link_ok(struct fc_lport *); | 80 | static int fcoe_link_ok(struct fc_lport *); |
| @@ -83,7 +82,6 @@ static int fcoe_link_ok(struct fc_lport *); | |||
| 83 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); | 82 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); |
| 84 | static int fcoe_hostlist_add(const struct fc_lport *); | 83 | static int fcoe_hostlist_add(const struct fc_lport *); |
| 85 | 84 | ||
| 86 | static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *); | ||
| 87 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); | 85 | static int fcoe_device_notification(struct notifier_block *, ulong, void *); |
| 88 | static void fcoe_dev_setup(void); | 86 | static void fcoe_dev_setup(void); |
| 89 | static void fcoe_dev_cleanup(void); | 87 | static void fcoe_dev_cleanup(void); |
| @@ -506,7 +504,7 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) | |||
| 506 | static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) | 504 | static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) |
| 507 | { | 505 | { |
| 508 | struct fcoe_port *port = lport_priv(lport); | 506 | struct fcoe_port *port = lport_priv(lport); |
| 509 | struct fcoe_interface *fcoe = port->fcoe; | 507 | struct fcoe_interface *fcoe = port->priv; |
| 510 | 508 | ||
| 511 | rtnl_lock(); | 509 | rtnl_lock(); |
| 512 | if (!is_zero_ether_addr(port->data_src_addr)) | 510 | if (!is_zero_ether_addr(port->data_src_addr)) |
| @@ -562,17 +560,6 @@ static int fcoe_lport_config(struct fc_lport *lport) | |||
| 562 | } | 560 | } |
| 563 | 561 | ||
| 564 | /** | 562 | /** |
| 565 | * fcoe_queue_timer() - The fcoe queue timer | ||
| 566 | * @lport: The local port | ||
| 567 | * | ||
| 568 | * Calls fcoe_check_wait_queue on timeout | ||
| 569 | */ | ||
| 570 | static void fcoe_queue_timer(ulong lport) | ||
| 571 | { | ||
| 572 | fcoe_check_wait_queue((struct fc_lport *)lport, NULL); | ||
| 573 | } | ||
| 574 | |||
| 575 | /** | ||
| 576 | * fcoe_get_wwn() - Get the world wide name from LLD if it supports it | 563 | * fcoe_get_wwn() - Get the world wide name from LLD if it supports it |
| 577 | * @netdev: the associated net device | 564 | * @netdev: the associated net device |
| 578 | * @wwn: the output WWN | 565 | * @wwn: the output WWN |
| @@ -651,7 +638,7 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) | |||
| 651 | 638 | ||
| 652 | /* Setup lport private data to point to fcoe softc */ | 639 | /* Setup lport private data to point to fcoe softc */ |
| 653 | port = lport_priv(lport); | 640 | port = lport_priv(lport); |
| 654 | fcoe = port->fcoe; | 641 | fcoe = port->priv; |
| 655 | 642 | ||
| 656 | /* | 643 | /* |
| 657 | * Determine max frame size based on underlying device and optional | 644 | * Determine max frame size based on underlying device and optional |
| @@ -761,7 +748,7 @@ bool fcoe_oem_match(struct fc_frame *fp) | |||
| 761 | static inline int fcoe_em_config(struct fc_lport *lport) | 748 | static inline int fcoe_em_config(struct fc_lport *lport) |
| 762 | { | 749 | { |
| 763 | struct fcoe_port *port = lport_priv(lport); | 750 | struct fcoe_port *port = lport_priv(lport); |
| 764 | struct fcoe_interface *fcoe = port->fcoe; | 751 | struct fcoe_interface *fcoe = port->priv; |
| 765 | struct fcoe_interface *oldfcoe = NULL; | 752 | struct fcoe_interface *oldfcoe = NULL; |
| 766 | struct net_device *old_real_dev, *cur_real_dev; | 753 | struct net_device *old_real_dev, *cur_real_dev; |
| 767 | u16 min_xid = FCOE_MIN_XID; | 754 | u16 min_xid = FCOE_MIN_XID; |
| @@ -845,7 +832,7 @@ skip_oem: | |||
| 845 | static void fcoe_if_destroy(struct fc_lport *lport) | 832 | static void fcoe_if_destroy(struct fc_lport *lport) |
| 846 | { | 833 | { |
| 847 | struct fcoe_port *port = lport_priv(lport); | 834 | struct fcoe_port *port = lport_priv(lport); |
| 848 | struct fcoe_interface *fcoe = port->fcoe; | 835 | struct fcoe_interface *fcoe = port->priv; |
| 849 | struct net_device *netdev = fcoe->netdev; | 836 | struct net_device *netdev = fcoe->netdev; |
| 850 | 837 | ||
| 851 | FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); | 838 | FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); |
| @@ -966,7 +953,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | |||
| 966 | } | 953 | } |
| 967 | port = lport_priv(lport); | 954 | port = lport_priv(lport); |
| 968 | port->lport = lport; | 955 | port->lport = lport; |
| 969 | port->fcoe = fcoe; | 956 | port->priv = fcoe; |
| 957 | port->max_queue_depth = FCOE_MAX_QUEUE_DEPTH; | ||
| 958 | port->min_queue_depth = FCOE_MIN_QUEUE_DEPTH; | ||
| 970 | INIT_WORK(&port->destroy_work, fcoe_destroy_work); | 959 | INIT_WORK(&port->destroy_work, fcoe_destroy_work); |
| 971 | 960 | ||
| 972 | /* configure a fc_lport including the exchange manager */ | 961 | /* configure a fc_lport including the exchange manager */ |
| @@ -1362,108 +1351,22 @@ err2: | |||
| 1362 | } | 1351 | } |
| 1363 | 1352 | ||
| 1364 | /** | 1353 | /** |
| 1365 | * fcoe_start_io() - Start FCoE I/O | 1354 | * fcoe_alloc_paged_crc_eof() - Allocate a page to be used for the trailer CRC |
| 1366 | * @skb: The packet to be transmitted | ||
| 1367 | * | ||
| 1368 | * This routine is called from the net device to start transmitting | ||
| 1369 | * FCoE packets. | ||
| 1370 | * | ||
| 1371 | * Returns: 0 for success | ||
| 1372 | */ | ||
| 1373 | static inline int fcoe_start_io(struct sk_buff *skb) | ||
| 1374 | { | ||
| 1375 | struct sk_buff *nskb; | ||
| 1376 | int rc; | ||
| 1377 | |||
| 1378 | nskb = skb_clone(skb, GFP_ATOMIC); | ||
| 1379 | rc = dev_queue_xmit(nskb); | ||
| 1380 | if (rc != 0) | ||
| 1381 | return rc; | ||
| 1382 | kfree_skb(skb); | ||
| 1383 | return 0; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | /** | ||
| 1387 | * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC | ||
| 1388 | * @skb: The packet to be transmitted | 1355 | * @skb: The packet to be transmitted |
| 1389 | * @tlen: The total length of the trailer | 1356 | * @tlen: The total length of the trailer |
| 1390 | * | 1357 | * |
| 1391 | * This routine allocates a page for frame trailers. The page is re-used if | ||
| 1392 | * there is enough room left on it for the current trailer. If there isn't | ||
| 1393 | * enough buffer left a new page is allocated for the trailer. Reference to | ||
| 1394 | * the page from this function as well as the skbs using the page fragments | ||
| 1395 | * ensure that the page is freed at the appropriate time. | ||
| 1396 | * | ||
| 1397 | * Returns: 0 for success | 1358 | * Returns: 0 for success |
| 1398 | */ | 1359 | */ |
| 1399 | static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) | 1360 | static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen) |
| 1400 | { | 1361 | { |
| 1401 | struct fcoe_percpu_s *fps; | 1362 | struct fcoe_percpu_s *fps; |
| 1402 | struct page *page; | 1363 | int rc; |
| 1403 | 1364 | ||
| 1404 | fps = &get_cpu_var(fcoe_percpu); | 1365 | fps = &get_cpu_var(fcoe_percpu); |
| 1405 | page = fps->crc_eof_page; | 1366 | rc = fcoe_get_paged_crc_eof(skb, tlen, fps); |
| 1406 | if (!page) { | ||
| 1407 | page = alloc_page(GFP_ATOMIC); | ||
| 1408 | if (!page) { | ||
| 1409 | put_cpu_var(fcoe_percpu); | ||
| 1410 | return -ENOMEM; | ||
| 1411 | } | ||
| 1412 | fps->crc_eof_page = page; | ||
| 1413 | fps->crc_eof_offset = 0; | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | get_page(page); | ||
| 1417 | skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, | ||
| 1418 | fps->crc_eof_offset, tlen); | ||
| 1419 | skb->len += tlen; | ||
| 1420 | skb->data_len += tlen; | ||
| 1421 | skb->truesize += tlen; | ||
| 1422 | fps->crc_eof_offset += sizeof(struct fcoe_crc_eof); | ||
| 1423 | |||
| 1424 | if (fps->crc_eof_offset >= PAGE_SIZE) { | ||
| 1425 | fps->crc_eof_page = NULL; | ||
| 1426 | fps->crc_eof_offset = 0; | ||
| 1427 | put_page(page); | ||
| 1428 | } | ||
| 1429 | put_cpu_var(fcoe_percpu); | 1367 | put_cpu_var(fcoe_percpu); |
| 1430 | return 0; | ||
| 1431 | } | ||
| 1432 | 1368 | ||
| 1433 | /** | 1369 | return rc; |
| 1434 | * fcoe_fc_crc() - Calculates the CRC for a given frame | ||
| 1435 | * @fp: The frame to be checksumed | ||
| 1436 | * | ||
| 1437 | * This uses crc32() routine to calculate the CRC for a frame | ||
| 1438 | * | ||
| 1439 | * Return: The 32 bit CRC value | ||
| 1440 | */ | ||
| 1441 | u32 fcoe_fc_crc(struct fc_frame *fp) | ||
| 1442 | { | ||
| 1443 | struct sk_buff *skb = fp_skb(fp); | ||
| 1444 | struct skb_frag_struct *frag; | ||
| 1445 | unsigned char *data; | ||
| 1446 | unsigned long off, len, clen; | ||
| 1447 | u32 crc; | ||
| 1448 | unsigned i; | ||
| 1449 | |||
| 1450 | crc = crc32(~0, skb->data, skb_headlen(skb)); | ||
| 1451 | |||
| 1452 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
| 1453 | frag = &skb_shinfo(skb)->frags[i]; | ||
| 1454 | off = frag->page_offset; | ||
| 1455 | len = frag->size; | ||
| 1456 | while (len > 0) { | ||
| 1457 | clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); | ||
| 1458 | data = kmap_atomic(frag->page + (off >> PAGE_SHIFT), | ||
| 1459 | KM_SKB_DATA_SOFTIRQ); | ||
| 1460 | crc = crc32(crc, data + (off & ~PAGE_MASK), clen); | ||
| 1461 | kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ); | ||
| 1462 | off += clen; | ||
| 1463 | len -= clen; | ||
| 1464 | } | ||
| 1465 | } | ||
| 1466 | return crc; | ||
| 1467 | } | 1370 | } |
| 1468 | 1371 | ||
| 1469 | /** | 1372 | /** |
| @@ -1486,7 +1389,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
| 1486 | unsigned int tlen; /* trailer length */ | 1389 | unsigned int tlen; /* trailer length */ |
| 1487 | unsigned int elen; /* eth header, may include vlan */ | 1390 | unsigned int elen; /* eth header, may include vlan */ |
| 1488 | struct fcoe_port *port = lport_priv(lport); | 1391 | struct fcoe_port *port = lport_priv(lport); |
| 1489 | struct fcoe_interface *fcoe = port->fcoe; | 1392 | struct fcoe_interface *fcoe = port->priv; |
| 1490 | u8 sof, eof; | 1393 | u8 sof, eof; |
| 1491 | struct fcoe_hdr *hp; | 1394 | struct fcoe_hdr *hp; |
| 1492 | 1395 | ||
| @@ -1527,7 +1430,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
| 1527 | /* copy port crc and eof to the skb buff */ | 1430 | /* copy port crc and eof to the skb buff */ |
| 1528 | if (skb_is_nonlinear(skb)) { | 1431 | if (skb_is_nonlinear(skb)) { |
| 1529 | skb_frag_t *frag; | 1432 | skb_frag_t *frag; |
| 1530 | if (fcoe_get_paged_crc_eof(skb, tlen)) { | 1433 | if (fcoe_alloc_paged_crc_eof(skb, tlen)) { |
| 1531 | kfree_skb(skb); | 1434 | kfree_skb(skb); |
| 1532 | return -ENOMEM; | 1435 | return -ENOMEM; |
| 1533 | } | 1436 | } |
| @@ -1636,7 +1539,7 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, | |||
| 1636 | if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type == FC_TYPE_FCP) | 1539 | if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type == FC_TYPE_FCP) |
| 1637 | return 0; | 1540 | return 0; |
| 1638 | 1541 | ||
| 1639 | fcoe = ((struct fcoe_port *)lport_priv(lport))->fcoe; | 1542 | fcoe = ((struct fcoe_port *)lport_priv(lport))->priv; |
| 1640 | if (is_fip_mode(&fcoe->ctlr) && fc_frame_payload_op(fp) == ELS_LOGO && | 1543 | if (is_fip_mode(&fcoe->ctlr) && fc_frame_payload_op(fp) == ELS_LOGO && |
| 1641 | ntoh24(fh->fh_s_id) == FC_FID_FLOGI) { | 1544 | ntoh24(fh->fh_s_id) == FC_FID_FLOGI) { |
| 1642 | FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n"); | 1545 | FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n"); |
| @@ -1771,64 +1674,6 @@ int fcoe_percpu_receive_thread(void *arg) | |||
| 1771 | } | 1674 | } |
| 1772 | 1675 | ||
| 1773 | /** | 1676 | /** |
| 1774 | * fcoe_check_wait_queue() - Attempt to clear the transmit backlog | ||
| 1775 | * @lport: The local port whose backlog is to be cleared | ||
| 1776 | * | ||
| 1777 | * This empties the wait_queue, dequeues the head of the wait_queue queue | ||
| 1778 | * and calls fcoe_start_io() for each packet. If all skb have been | ||
| 1779 | * transmitted it returns the qlen. If an error occurs it restores | ||
| 1780 | * wait_queue (to try again later) and returns -1. | ||
| 1781 | * | ||
| 1782 | * The wait_queue is used when the skb transmit fails. The failed skb | ||
| 1783 | * will go in the wait_queue which will be emptied by the timer function or | ||
| 1784 | * by the next skb transmit. | ||
| 1785 | */ | ||
| 1786 | static void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb) | ||
| 1787 | { | ||
| 1788 | struct fcoe_port *port = lport_priv(lport); | ||
| 1789 | int rc; | ||
| 1790 | |||
| 1791 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
| 1792 | |||
| 1793 | if (skb) | ||
| 1794 | __skb_queue_tail(&port->fcoe_pending_queue, skb); | ||
| 1795 | |||
| 1796 | if (port->fcoe_pending_queue_active) | ||
| 1797 | goto out; | ||
| 1798 | port->fcoe_pending_queue_active = 1; | ||
| 1799 | |||
| 1800 | while (port->fcoe_pending_queue.qlen) { | ||
| 1801 | /* keep qlen > 0 until fcoe_start_io succeeds */ | ||
| 1802 | port->fcoe_pending_queue.qlen++; | ||
| 1803 | skb = __skb_dequeue(&port->fcoe_pending_queue); | ||
| 1804 | |||
| 1805 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
| 1806 | rc = fcoe_start_io(skb); | ||
| 1807 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
| 1808 | |||
| 1809 | if (rc) { | ||
| 1810 | __skb_queue_head(&port->fcoe_pending_queue, skb); | ||
| 1811 | /* undo temporary increment above */ | ||
| 1812 | port->fcoe_pending_queue.qlen--; | ||
| 1813 | break; | ||
| 1814 | } | ||
| 1815 | /* undo temporary increment above */ | ||
| 1816 | port->fcoe_pending_queue.qlen--; | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) | ||
| 1820 | lport->qfull = 0; | ||
| 1821 | if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer)) | ||
| 1822 | mod_timer(&port->timer, jiffies + 2); | ||
| 1823 | port->fcoe_pending_queue_active = 0; | ||
| 1824 | out: | ||
| 1825 | if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) | ||
| 1826 | lport->qfull = 1; | ||
| 1827 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
| 1828 | return; | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | /** | ||
| 1832 | * fcoe_dev_setup() - Setup the link change notification interface | 1677 | * fcoe_dev_setup() - Setup the link change notification interface |
| 1833 | */ | 1678 | */ |
| 1834 | static void fcoe_dev_setup(void) | 1679 | static void fcoe_dev_setup(void) |
| @@ -2180,8 +2025,7 @@ out_nodev: | |||
| 2180 | */ | 2025 | */ |
| 2181 | int fcoe_link_speed_update(struct fc_lport *lport) | 2026 | int fcoe_link_speed_update(struct fc_lport *lport) |
| 2182 | { | 2027 | { |
| 2183 | struct fcoe_port *port = lport_priv(lport); | 2028 | struct net_device *netdev = fcoe_netdev(lport); |
| 2184 | struct net_device *netdev = port->fcoe->netdev; | ||
| 2185 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; | 2029 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; |
| 2186 | 2030 | ||
| 2187 | if (!dev_ethtool_get_settings(netdev, &ecmd)) { | 2031 | if (!dev_ethtool_get_settings(netdev, &ecmd)) { |
| @@ -2212,8 +2056,7 @@ int fcoe_link_speed_update(struct fc_lport *lport) | |||
| 2212 | */ | 2056 | */ |
| 2213 | int fcoe_link_ok(struct fc_lport *lport) | 2057 | int fcoe_link_ok(struct fc_lport *lport) |
| 2214 | { | 2058 | { |
| 2215 | struct fcoe_port *port = lport_priv(lport); | 2059 | struct net_device *netdev = fcoe_netdev(lport); |
| 2216 | struct net_device *netdev = port->fcoe->netdev; | ||
| 2217 | 2060 | ||
| 2218 | if (netif_oper_up(netdev)) | 2061 | if (netif_oper_up(netdev)) |
| 2219 | return 0; | 2062 | return 0; |
| @@ -2277,24 +2120,6 @@ void fcoe_percpu_clean(struct fc_lport *lport) | |||
| 2277 | } | 2120 | } |
| 2278 | 2121 | ||
| 2279 | /** | 2122 | /** |
| 2280 | * fcoe_clean_pending_queue() - Dequeue a skb and free it | ||
| 2281 | * @lport: The local port to dequeue a skb on | ||
| 2282 | */ | ||
| 2283 | void fcoe_clean_pending_queue(struct fc_lport *lport) | ||
| 2284 | { | ||
| 2285 | struct fcoe_port *port = lport_priv(lport); | ||
| 2286 | struct sk_buff *skb; | ||
| 2287 | |||
| 2288 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
| 2289 | while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) { | ||
| 2290 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
| 2291 | kfree_skb(skb); | ||
| 2292 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
| 2293 | } | ||
| 2294 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
| 2295 | } | ||
| 2296 | |||
| 2297 | /** | ||
| 2298 | * fcoe_reset() - Reset a local port | 2123 | * fcoe_reset() - Reset a local port |
| 2299 | * @shost: The SCSI host associated with the local port to be reset | 2124 | * @shost: The SCSI host associated with the local port to be reset |
| 2300 | * | 2125 | * |
| @@ -2361,7 +2186,7 @@ static int fcoe_hostlist_add(const struct fc_lport *lport) | |||
| 2361 | fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport)); | 2186 | fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport)); |
| 2362 | if (!fcoe) { | 2187 | if (!fcoe) { |
| 2363 | port = lport_priv(lport); | 2188 | port = lport_priv(lport); |
| 2364 | fcoe = port->fcoe; | 2189 | fcoe = port->priv; |
| 2365 | list_add_tail(&fcoe->list, &fcoe_hostlist); | 2190 | list_add_tail(&fcoe->list, &fcoe_hostlist); |
| 2366 | } | 2191 | } |
| 2367 | return 0; | 2192 | return 0; |
| @@ -2555,7 +2380,7 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did, | |||
| 2555 | void *arg, u32 timeout) | 2380 | void *arg, u32 timeout) |
| 2556 | { | 2381 | { |
| 2557 | struct fcoe_port *port = lport_priv(lport); | 2382 | struct fcoe_port *port = lport_priv(lport); |
| 2558 | struct fcoe_interface *fcoe = port->fcoe; | 2383 | struct fcoe_interface *fcoe = port->priv; |
| 2559 | struct fcoe_ctlr *fip = &fcoe->ctlr; | 2384 | struct fcoe_ctlr *fip = &fcoe->ctlr; |
| 2560 | struct fc_frame_header *fh = fc_frame_header_get(fp); | 2385 | struct fc_frame_header *fh = fc_frame_header_get(fp); |
| 2561 | 2386 | ||
| @@ -2588,7 +2413,7 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled) | |||
| 2588 | struct Scsi_Host *shost = vport_to_shost(vport); | 2413 | struct Scsi_Host *shost = vport_to_shost(vport); |
| 2589 | struct fc_lport *n_port = shost_priv(shost); | 2414 | struct fc_lport *n_port = shost_priv(shost); |
| 2590 | struct fcoe_port *port = lport_priv(n_port); | 2415 | struct fcoe_port *port = lport_priv(n_port); |
| 2591 | struct fcoe_interface *fcoe = port->fcoe; | 2416 | struct fcoe_interface *fcoe = port->priv; |
| 2592 | struct net_device *netdev = fcoe->netdev; | 2417 | struct net_device *netdev = fcoe->netdev; |
| 2593 | struct fc_lport *vn_port; | 2418 | struct fc_lport *vn_port; |
| 2594 | 2419 | ||
| @@ -2732,7 +2557,7 @@ static void fcoe_set_port_id(struct fc_lport *lport, | |||
| 2732 | u32 port_id, struct fc_frame *fp) | 2557 | u32 port_id, struct fc_frame *fp) |
| 2733 | { | 2558 | { |
| 2734 | struct fcoe_port *port = lport_priv(lport); | 2559 | struct fcoe_port *port = lport_priv(lport); |
| 2735 | struct fcoe_interface *fcoe = port->fcoe; | 2560 | struct fcoe_interface *fcoe = port->priv; |
| 2736 | 2561 | ||
| 2737 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) | 2562 | if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) |
| 2738 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); | 2563 | fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); |
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index c69b2c56c2d1..d775128398e9 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
| 25 | 25 | ||
| 26 | #define FCOE_MAX_QUEUE_DEPTH 256 | 26 | #define FCOE_MAX_QUEUE_DEPTH 256 |
| 27 | #define FCOE_LOW_QUEUE_DEPTH 32 | 27 | #define FCOE_MIN_QUEUE_DEPTH 32 |
| 28 | 28 | ||
| 29 | #define FCOE_WORD_TO_BYTE 4 | 29 | #define FCOE_WORD_TO_BYTE 4 |
| 30 | 30 | ||
| @@ -71,21 +71,6 @@ do { \ | |||
| 71 | netdev->name, ##args);) | 71 | netdev->name, ##args);) |
| 72 | 72 | ||
| 73 | /** | 73 | /** |
| 74 | * struct fcoe_percpu_s - The per-CPU context for FCoE receive threads | ||
| 75 | * @thread: The thread context | ||
| 76 | * @fcoe_rx_list: The queue of pending packets to process | ||
| 77 | * @page: The memory page for calculating frame trailer CRCs | ||
| 78 | * @crc_eof_offset: The offset into the CRC page pointing to available | ||
| 79 | * memory for a new trailer | ||
| 80 | */ | ||
| 81 | struct fcoe_percpu_s { | ||
| 82 | struct task_struct *thread; | ||
| 83 | struct sk_buff_head fcoe_rx_list; | ||
| 84 | struct page *crc_eof_page; | ||
| 85 | int crc_eof_offset; | ||
| 86 | }; | ||
| 87 | |||
| 88 | /** | ||
| 89 | * struct fcoe_interface - A FCoE interface | 74 | * struct fcoe_interface - A FCoE interface |
| 90 | * @list: Handle for a list of FCoE interfaces | 75 | * @list: Handle for a list of FCoE interfaces |
| 91 | * @netdev: The associated net device | 76 | * @netdev: The associated net device |
| @@ -108,30 +93,6 @@ struct fcoe_interface { | |||
| 108 | struct kref kref; | 93 | struct kref kref; |
| 109 | }; | 94 | }; |
| 110 | 95 | ||
| 111 | /** | ||
| 112 | * struct fcoe_port - The FCoE private structure | ||
| 113 | * @fcoe: The associated fcoe interface | ||
| 114 | * @lport: The associated local port | ||
| 115 | * @fcoe_pending_queue: The pending Rx queue of skbs | ||
| 116 | * @fcoe_pending_queue_active: Indicates if the pending queue is active | ||
| 117 | * @timer: The queue timer | ||
| 118 | * @destroy_work: Handle for work context | ||
| 119 | * (to prevent RTNL deadlocks) | ||
| 120 | * @data_srt_addr: Source address for data | ||
| 121 | * | ||
| 122 | * An instance of this structure is to be allocated along with the | ||
| 123 | * Scsi_Host and libfc fc_lport structures. | ||
| 124 | */ | ||
| 125 | struct fcoe_port { | ||
| 126 | struct fcoe_interface *fcoe; | ||
| 127 | struct fc_lport *lport; | ||
| 128 | struct sk_buff_head fcoe_pending_queue; | ||
| 129 | u8 fcoe_pending_queue_active; | ||
| 130 | struct timer_list timer; | ||
| 131 | struct work_struct destroy_work; | ||
| 132 | u8 data_src_addr[ETH_ALEN]; | ||
| 133 | }; | ||
| 134 | |||
| 135 | #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) | 96 | #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) |
| 136 | 97 | ||
| 137 | /** | 98 | /** |
| @@ -140,7 +101,8 @@ struct fcoe_port { | |||
| 140 | */ | 101 | */ |
| 141 | static inline struct net_device *fcoe_netdev(const struct fc_lport *lport) | 102 | static inline struct net_device *fcoe_netdev(const struct fc_lport *lport) |
| 142 | { | 103 | { |
| 143 | return ((struct fcoe_port *)lport_priv(lport))->fcoe->netdev; | 104 | return ((struct fcoe_interface *) |
| 105 | ((struct fcoe_port *)lport_priv(lport))->priv)->netdev; | ||
| 144 | } | 106 | } |
| 145 | 107 | ||
| 146 | #endif /* _FCOE_H_ */ | 108 | #endif /* _FCOE_H_ */ |
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index e5aef5639124..745eb9a22d64 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
| 24 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
| 25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
| 26 | #include <linux/crc32.h> | ||
| 26 | #include <scsi/libfcoe.h> | 27 | #include <scsi/libfcoe.h> |
| 27 | 28 | ||
| 28 | #include "libfcoe.h" | 29 | #include "libfcoe.h" |
| @@ -75,6 +76,205 @@ __MODULE_PARM_TYPE(disable, "string"); | |||
| 75 | MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); | 76 | MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); |
| 76 | 77 | ||
| 77 | /** | 78 | /** |
| 79 | * fcoe_fc_crc() - Calculates the CRC for a given frame | ||
| 80 | * @fp: The frame to be checksumed | ||
| 81 | * | ||
| 82 | * This uses crc32() routine to calculate the CRC for a frame | ||
| 83 | * | ||
| 84 | * Return: The 32 bit CRC value | ||
| 85 | */ | ||
| 86 | u32 fcoe_fc_crc(struct fc_frame *fp) | ||
| 87 | { | ||
| 88 | struct sk_buff *skb = fp_skb(fp); | ||
| 89 | struct skb_frag_struct *frag; | ||
| 90 | unsigned char *data; | ||
| 91 | unsigned long off, len, clen; | ||
| 92 | u32 crc; | ||
| 93 | unsigned i; | ||
| 94 | |||
| 95 | crc = crc32(~0, skb->data, skb_headlen(skb)); | ||
| 96 | |||
| 97 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
| 98 | frag = &skb_shinfo(skb)->frags[i]; | ||
| 99 | off = frag->page_offset; | ||
| 100 | len = frag->size; | ||
| 101 | while (len > 0) { | ||
| 102 | clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK)); | ||
| 103 | data = kmap_atomic(frag->page + (off >> PAGE_SHIFT), | ||
| 104 | KM_SKB_DATA_SOFTIRQ); | ||
| 105 | crc = crc32(crc, data + (off & ~PAGE_MASK), clen); | ||
| 106 | kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ); | ||
| 107 | off += clen; | ||
| 108 | len -= clen; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | return crc; | ||
| 112 | } | ||
| 113 | EXPORT_SYMBOL_GPL(fcoe_fc_crc); | ||
| 114 | |||
| 115 | /** | ||
| 116 | * fcoe_start_io() - Start FCoE I/O | ||
| 117 | * @skb: The packet to be transmitted | ||
| 118 | * | ||
| 119 | * This routine is called from the net device to start transmitting | ||
| 120 | * FCoE packets. | ||
| 121 | * | ||
| 122 | * Returns: 0 for success | ||
| 123 | */ | ||
| 124 | int fcoe_start_io(struct sk_buff *skb) | ||
| 125 | { | ||
| 126 | struct sk_buff *nskb; | ||
| 127 | int rc; | ||
| 128 | |||
| 129 | nskb = skb_clone(skb, GFP_ATOMIC); | ||
| 130 | if (!nskb) | ||
| 131 | return -ENOMEM; | ||
| 132 | rc = dev_queue_xmit(nskb); | ||
| 133 | if (rc != 0) | ||
| 134 | return rc; | ||
| 135 | kfree_skb(skb); | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | EXPORT_SYMBOL_GPL(fcoe_start_io); | ||
| 139 | |||
| 140 | |||
| 141 | /** | ||
| 142 | * fcoe_clean_pending_queue() - Dequeue a skb and free it | ||
| 143 | * @lport: The local port to dequeue a skb on | ||
| 144 | */ | ||
| 145 | void fcoe_clean_pending_queue(struct fc_lport *lport) | ||
| 146 | { | ||
| 147 | struct fcoe_port *port = lport_priv(lport); | ||
| 148 | struct sk_buff *skb; | ||
| 149 | |||
| 150 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
| 151 | while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) { | ||
| 152 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
| 153 | kfree_skb(skb); | ||
| 154 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
| 155 | } | ||
| 156 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
| 157 | } | ||
| 158 | EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); | ||
| 159 | |||
| 160 | /** | ||
| 161 | * fcoe_check_wait_queue() - Attempt to clear the transmit backlog | ||
| 162 | * @lport: The local port whose backlog is to be cleared | ||
| 163 | * | ||
| 164 | * This empties the wait_queue, dequeues the head of the wait_queue queue | ||
| 165 | * and calls fcoe_start_io() for each packet. If all skb have been | ||
| 166 | * transmitted it returns the qlen. If an error occurs it restores | ||
| 167 | * wait_queue (to try again later) and returns -1. | ||
| 168 | * | ||
| 169 | * The wait_queue is used when the skb transmit fails. The failed skb | ||
| 170 | * will go in the wait_queue which will be emptied by the timer function or | ||
| 171 | * by the next skb transmit. | ||
| 172 | */ | ||
| 173 | void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb) | ||
| 174 | { | ||
| 175 | struct fcoe_port *port = lport_priv(lport); | ||
| 176 | int rc; | ||
| 177 | |||
| 178 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
| 179 | |||
| 180 | if (skb) | ||
| 181 | __skb_queue_tail(&port->fcoe_pending_queue, skb); | ||
| 182 | |||
| 183 | if (port->fcoe_pending_queue_active) | ||
| 184 | goto out; | ||
| 185 | port->fcoe_pending_queue_active = 1; | ||
| 186 | |||
| 187 | while (port->fcoe_pending_queue.qlen) { | ||
| 188 | /* keep qlen > 0 until fcoe_start_io succeeds */ | ||
| 189 | port->fcoe_pending_queue.qlen++; | ||
| 190 | skb = __skb_dequeue(&port->fcoe_pending_queue); | ||
| 191 | |||
| 192 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
| 193 | rc = fcoe_start_io(skb); | ||
| 194 | spin_lock_bh(&port->fcoe_pending_queue.lock); | ||
| 195 | |||
| 196 | if (rc) { | ||
| 197 | __skb_queue_head(&port->fcoe_pending_queue, skb); | ||
| 198 | /* undo temporary increment above */ | ||
| 199 | port->fcoe_pending_queue.qlen--; | ||
| 200 | break; | ||
| 201 | } | ||
| 202 | /* undo temporary increment above */ | ||
| 203 | port->fcoe_pending_queue.qlen--; | ||
| 204 | } | ||
| 205 | |||
| 206 | if (port->fcoe_pending_queue.qlen < port->min_queue_depth) | ||
| 207 | lport->qfull = 0; | ||
| 208 | if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer)) | ||
| 209 | mod_timer(&port->timer, jiffies + 2); | ||
| 210 | port->fcoe_pending_queue_active = 0; | ||
| 211 | out: | ||
| 212 | if (port->fcoe_pending_queue.qlen > port->max_queue_depth) | ||
| 213 | lport->qfull = 1; | ||
| 214 | spin_unlock_bh(&port->fcoe_pending_queue.lock); | ||
| 215 | } | ||
| 216 | EXPORT_SYMBOL_GPL(fcoe_check_wait_queue); | ||
| 217 | |||
| 218 | /** | ||
| 219 | * fcoe_queue_timer() - The fcoe queue timer | ||
| 220 | * @lport: The local port | ||
| 221 | * | ||
| 222 | * Calls fcoe_check_wait_queue on timeout | ||
| 223 | */ | ||
| 224 | void fcoe_queue_timer(ulong lport) | ||
| 225 | { | ||
| 226 | fcoe_check_wait_queue((struct fc_lport *)lport, NULL); | ||
| 227 | } | ||
| 228 | EXPORT_SYMBOL_GPL(fcoe_queue_timer); | ||
| 229 | |||
| 230 | /** | ||
| 231 | * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC | ||
| 232 | * @skb: The packet to be transmitted | ||
| 233 | * @tlen: The total length of the trailer | ||
| 234 | * @fps: The fcoe context | ||
| 235 | * | ||
| 236 | * This routine allocates a page for frame trailers. The page is re-used if | ||
| 237 | * there is enough room left on it for the current trailer. If there isn't | ||
| 238 | * enough buffer left a new page is allocated for the trailer. Reference to | ||
| 239 | * the page from this function as well as the skbs using the page fragments | ||
| 240 | * ensure that the page is freed at the appropriate time. | ||
| 241 | * | ||
| 242 | * Returns: 0 for success | ||
| 243 | */ | ||
| 244 | int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen, | ||
| 245 | struct fcoe_percpu_s *fps) | ||
| 246 | { | ||
| 247 | struct page *page; | ||
| 248 | |||
| 249 | page = fps->crc_eof_page; | ||
| 250 | if (!page) { | ||
| 251 | page = alloc_page(GFP_ATOMIC); | ||
| 252 | if (!page) | ||
| 253 | return -ENOMEM; | ||
| 254 | |||
| 255 | fps->crc_eof_page = page; | ||
| 256 | fps->crc_eof_offset = 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | get_page(page); | ||
| 260 | skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, | ||
| 261 | fps->crc_eof_offset, tlen); | ||
| 262 | skb->len += tlen; | ||
| 263 | skb->data_len += tlen; | ||
| 264 | skb->truesize += tlen; | ||
| 265 | fps->crc_eof_offset += sizeof(struct fcoe_crc_eof); | ||
| 266 | |||
| 267 | if (fps->crc_eof_offset >= PAGE_SIZE) { | ||
| 268 | fps->crc_eof_page = NULL; | ||
| 269 | fps->crc_eof_offset = 0; | ||
| 270 | put_page(page); | ||
| 271 | } | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof); | ||
| 276 | |||
| 277 | /** | ||
| 78 | * fcoe_transport_lookup - find an fcoe transport that matches a netdev | 278 | * fcoe_transport_lookup - find an fcoe transport that matches a netdev |
| 79 | * @netdev: The netdev to look for from all attached transports | 279 | * @netdev: The netdev to look for from all attached transports |
| 80 | * | 280 | * |
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index efb6ae5b94ad..e5024634bfab 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h | |||
| @@ -221,6 +221,8 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_lport *, | |||
| 221 | u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); | 221 | u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int); |
| 222 | int fcoe_libfc_config(struct fc_lport *, struct fcoe_ctlr *, | 222 | int fcoe_libfc_config(struct fc_lport *, struct fcoe_ctlr *, |
| 223 | const struct libfc_function_template *, int init_fcp); | 223 | const struct libfc_function_template *, int init_fcp); |
| 224 | u32 fcoe_fc_crc(struct fc_frame *fp); | ||
| 225 | int fcoe_start_io(struct sk_buff *skb); | ||
| 224 | 226 | ||
| 225 | /** | 227 | /** |
| 226 | * is_fip_mode() - returns true if FIP mode selected. | 228 | * is_fip_mode() - returns true if FIP mode selected. |
| @@ -267,6 +269,55 @@ struct fcoe_transport { | |||
| 267 | }; | 269 | }; |
| 268 | 270 | ||
| 269 | /** | 271 | /** |
| 272 | * struct fcoe_percpu_s - The context for FCoE receive thread(s) | ||
| 273 | * @thread: The thread context | ||
| 274 | * @fcoe_rx_list: The queue of pending packets to process | ||
| 275 | * @page: The memory page for calculating frame trailer CRCs | ||
| 276 | * @crc_eof_offset: The offset into the CRC page pointing to available | ||
| 277 | * memory for a new trailer | ||
| 278 | */ | ||
| 279 | struct fcoe_percpu_s { | ||
| 280 | struct task_struct *thread; | ||
| 281 | struct sk_buff_head fcoe_rx_list; | ||
| 282 | struct page *crc_eof_page; | ||
| 283 | int crc_eof_offset; | ||
| 284 | }; | ||
| 285 | |||
| 286 | /** | ||
| 287 | * struct fcoe_port - The FCoE private structure | ||
| 288 | * @priv: The associated fcoe interface. The structure is | ||
| 289 | * defined by the low level driver | ||
| 290 | * @lport: The associated local port | ||
| 291 | * @fcoe_pending_queue: The pending Rx queue of skbs | ||
| 292 | * @fcoe_pending_queue_active: Indicates if the pending queue is active | ||
| 293 | * @max_queue_depth: Max queue depth of pending queue | ||
| 294 | * @min_queue_depth: Min queue depth of pending queue | ||
| 295 | * @timer: The queue timer | ||
| 296 | * @destroy_work: Handle for work context | ||
| 297 | * (to prevent RTNL deadlocks) | ||
| 298 | * @data_srt_addr: Source address for data | ||
| 299 | * | ||
| 300 | * An instance of this structure is to be allocated along with the | ||
| 301 | * Scsi_Host and libfc fc_lport structures. | ||
| 302 | */ | ||
| 303 | struct fcoe_port { | ||
| 304 | void *priv; | ||
| 305 | struct fc_lport *lport; | ||
| 306 | struct sk_buff_head fcoe_pending_queue; | ||
| 307 | u8 fcoe_pending_queue_active; | ||
| 308 | u32 max_queue_depth; | ||
| 309 | u32 min_queue_depth; | ||
| 310 | struct timer_list timer; | ||
| 311 | struct work_struct destroy_work; | ||
| 312 | u8 data_src_addr[ETH_ALEN]; | ||
| 313 | }; | ||
| 314 | void fcoe_clean_pending_queue(struct fc_lport *); | ||
| 315 | void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb); | ||
| 316 | void fcoe_queue_timer(ulong lport); | ||
| 317 | int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen, | ||
| 318 | struct fcoe_percpu_s *fps); | ||
| 319 | |||
| 320 | /** | ||
| 270 | * struct netdev_list | 321 | * struct netdev_list |
| 271 | * A mapping from netdevice to fcoe_transport | 322 | * A mapping from netdevice to fcoe_transport |
| 272 | */ | 323 | */ |
