diff options
Diffstat (limited to 'drivers/s390/net/qeth_main.c')
-rw-r--r-- | drivers/s390/net/qeth_main.c | 460 |
1 files changed, 337 insertions, 123 deletions
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 86582cf1e19e..692003c9f896 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -196,7 +196,6 @@ qeth_notifier_register(struct task_struct *p, int signum) | |||
196 | { | 196 | { |
197 | struct qeth_notify_list_struct *n_entry; | 197 | struct qeth_notify_list_struct *n_entry; |
198 | 198 | ||
199 | |||
200 | /*check first if entry already exists*/ | 199 | /*check first if entry already exists*/ |
201 | spin_lock(&qeth_notify_lock); | 200 | spin_lock(&qeth_notify_lock); |
202 | list_for_each_entry(n_entry, &qeth_notify_list, list) { | 201 | list_for_each_entry(n_entry, &qeth_notify_list, list) { |
@@ -511,7 +510,7 @@ static int | |||
511 | __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) | 510 | __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) |
512 | { | 511 | { |
513 | struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data; | 512 | struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data; |
514 | int rc = 0; | 513 | int rc = 0, rc2 = 0, rc3 = 0; |
515 | enum qeth_card_states recover_flag; | 514 | enum qeth_card_states recover_flag; |
516 | 515 | ||
517 | QETH_DBF_TEXT(setup, 3, "setoffl"); | 516 | QETH_DBF_TEXT(setup, 3, "setoffl"); |
@@ -523,11 +522,13 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) | |||
523 | CARD_BUS_ID(card)); | 522 | CARD_BUS_ID(card)); |
524 | return -ERESTARTSYS; | 523 | return -ERESTARTSYS; |
525 | } | 524 | } |
526 | if ((rc = ccw_device_set_offline(CARD_DDEV(card))) || | 525 | rc = ccw_device_set_offline(CARD_DDEV(card)); |
527 | (rc = ccw_device_set_offline(CARD_WDEV(card))) || | 526 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); |
528 | (rc = ccw_device_set_offline(CARD_RDEV(card)))) { | 527 | rc3 = ccw_device_set_offline(CARD_RDEV(card)); |
528 | if (!rc) | ||
529 | rc = (rc2) ? rc2 : rc3; | ||
530 | if (rc) | ||
529 | QETH_DBF_TEXT_(setup, 2, "1err%d", rc); | 531 | QETH_DBF_TEXT_(setup, 2, "1err%d", rc); |
530 | } | ||
531 | if (recover_flag == CARD_STATE_UP) | 532 | if (recover_flag == CARD_STATE_UP) |
532 | card->state = CARD_STATE_RECOVER; | 533 | card->state = CARD_STATE_RECOVER; |
533 | qeth_notify_processes(); | 534 | qeth_notify_processes(); |
@@ -1022,7 +1023,10 @@ qeth_set_intial_options(struct qeth_card *card) | |||
1022 | card->options.fake_broadcast = 0; | 1023 | card->options.fake_broadcast = 0; |
1023 | card->options.add_hhlen = DEFAULT_ADD_HHLEN; | 1024 | card->options.add_hhlen = DEFAULT_ADD_HHLEN; |
1024 | card->options.fake_ll = 0; | 1025 | card->options.fake_ll = 0; |
1025 | card->options.layer2 = 0; | 1026 | if (card->info.type == QETH_CARD_TYPE_OSN) |
1027 | card->options.layer2 = 1; | ||
1028 | else | ||
1029 | card->options.layer2 = 0; | ||
1026 | } | 1030 | } |
1027 | 1031 | ||
1028 | /** | 1032 | /** |
@@ -1046,6 +1050,7 @@ qeth_setup_card(struct qeth_card *card) | |||
1046 | spin_lock_init(&card->vlanlock); | 1050 | spin_lock_init(&card->vlanlock); |
1047 | card->vlangrp = NULL; | 1051 | card->vlangrp = NULL; |
1048 | #endif | 1052 | #endif |
1053 | spin_lock_init(&card->lock); | ||
1049 | spin_lock_init(&card->ip_lock); | 1054 | spin_lock_init(&card->ip_lock); |
1050 | spin_lock_init(&card->thread_mask_lock); | 1055 | spin_lock_init(&card->thread_mask_lock); |
1051 | card->thread_start_mask = 0; | 1056 | card->thread_start_mask = 0; |
@@ -1110,19 +1115,20 @@ qeth_determine_card_type(struct qeth_card *card) | |||
1110 | 1115 | ||
1111 | QETH_DBF_TEXT(setup, 2, "detcdtyp"); | 1116 | QETH_DBF_TEXT(setup, 2, "detcdtyp"); |
1112 | 1117 | ||
1118 | card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; | ||
1119 | card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; | ||
1113 | while (known_devices[i][4]) { | 1120 | while (known_devices[i][4]) { |
1114 | if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) && | 1121 | if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) && |
1115 | (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) { | 1122 | (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) { |
1116 | card->info.type = known_devices[i][4]; | 1123 | card->info.type = known_devices[i][4]; |
1124 | card->qdio.no_out_queues = known_devices[i][8]; | ||
1125 | card->info.is_multicast_different = known_devices[i][9]; | ||
1117 | if (is_1920_device(card)) { | 1126 | if (is_1920_device(card)) { |
1118 | PRINT_INFO("Priority Queueing not able " | 1127 | PRINT_INFO("Priority Queueing not able " |
1119 | "due to hardware limitations!\n"); | 1128 | "due to hardware limitations!\n"); |
1120 | card->qdio.no_out_queues = 1; | 1129 | card->qdio.no_out_queues = 1; |
1121 | card->qdio.default_out_queue = 0; | 1130 | card->qdio.default_out_queue = 0; |
1122 | } else { | 1131 | } |
1123 | card->qdio.no_out_queues = known_devices[i][8]; | ||
1124 | } | ||
1125 | card->info.is_multicast_different = known_devices[i][9]; | ||
1126 | return 0; | 1132 | return 0; |
1127 | } | 1133 | } |
1128 | i++; | 1134 | i++; |
@@ -1146,6 +1152,8 @@ qeth_probe_device(struct ccwgroup_device *gdev) | |||
1146 | if (!get_device(dev)) | 1152 | if (!get_device(dev)) |
1147 | return -ENODEV; | 1153 | return -ENODEV; |
1148 | 1154 | ||
1155 | QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id); | ||
1156 | |||
1149 | card = qeth_alloc_card(); | 1157 | card = qeth_alloc_card(); |
1150 | if (!card) { | 1158 | if (!card) { |
1151 | put_device(dev); | 1159 | put_device(dev); |
@@ -1155,28 +1163,27 @@ qeth_probe_device(struct ccwgroup_device *gdev) | |||
1155 | card->read.ccwdev = gdev->cdev[0]; | 1163 | card->read.ccwdev = gdev->cdev[0]; |
1156 | card->write.ccwdev = gdev->cdev[1]; | 1164 | card->write.ccwdev = gdev->cdev[1]; |
1157 | card->data.ccwdev = gdev->cdev[2]; | 1165 | card->data.ccwdev = gdev->cdev[2]; |
1158 | |||
1159 | if ((rc = qeth_setup_card(card))){ | ||
1160 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); | ||
1161 | put_device(dev); | ||
1162 | qeth_free_card(card); | ||
1163 | return rc; | ||
1164 | } | ||
1165 | gdev->dev.driver_data = card; | 1166 | gdev->dev.driver_data = card; |
1166 | card->gdev = gdev; | 1167 | card->gdev = gdev; |
1167 | gdev->cdev[0]->handler = qeth_irq; | 1168 | gdev->cdev[0]->handler = qeth_irq; |
1168 | gdev->cdev[1]->handler = qeth_irq; | 1169 | gdev->cdev[1]->handler = qeth_irq; |
1169 | gdev->cdev[2]->handler = qeth_irq; | 1170 | gdev->cdev[2]->handler = qeth_irq; |
1170 | 1171 | ||
1171 | rc = qeth_create_device_attributes(dev); | 1172 | if ((rc = qeth_determine_card_type(card))){ |
1172 | if (rc) { | 1173 | PRINT_WARN("%s: not a valid card type\n", __func__); |
1174 | QETH_DBF_TEXT_(setup, 2, "3err%d", rc); | ||
1175 | put_device(dev); | ||
1176 | qeth_free_card(card); | ||
1177 | return rc; | ||
1178 | } | ||
1179 | if ((rc = qeth_setup_card(card))){ | ||
1180 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); | ||
1173 | put_device(dev); | 1181 | put_device(dev); |
1174 | qeth_free_card(card); | 1182 | qeth_free_card(card); |
1175 | return rc; | 1183 | return rc; |
1176 | } | 1184 | } |
1177 | if ((rc = qeth_determine_card_type(card))){ | 1185 | rc = qeth_create_device_attributes(dev); |
1178 | PRINT_WARN("%s: not a valid card type\n", __func__); | 1186 | if (rc) { |
1179 | QETH_DBF_TEXT_(setup, 2, "3err%d", rc); | ||
1180 | put_device(dev); | 1187 | put_device(dev); |
1181 | qeth_free_card(card); | 1188 | qeth_free_card(card); |
1182 | return rc; | 1189 | return rc; |
@@ -1626,16 +1633,6 @@ qeth_cmd_timeout(unsigned long data) | |||
1626 | spin_unlock_irqrestore(&reply->card->lock, flags); | 1633 | spin_unlock_irqrestore(&reply->card->lock, flags); |
1627 | } | 1634 | } |
1628 | 1635 | ||
1629 | static void | ||
1630 | qeth_reset_ip_addresses(struct qeth_card *card) | ||
1631 | { | ||
1632 | QETH_DBF_TEXT(trace, 2, "rstipadd"); | ||
1633 | |||
1634 | qeth_clear_ip_list(card, 0, 1); | ||
1635 | /* this function will also schedule the SET_IP_THREAD */ | ||
1636 | qeth_set_multicast_list(card->dev); | ||
1637 | } | ||
1638 | |||
1639 | static struct qeth_ipa_cmd * | 1636 | static struct qeth_ipa_cmd * |
1640 | qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) | 1637 | qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) |
1641 | { | 1638 | { |
@@ -1664,10 +1661,11 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) | |||
1664 | "IP address reset.\n", | 1661 | "IP address reset.\n", |
1665 | QETH_CARD_IFNAME(card), | 1662 | QETH_CARD_IFNAME(card), |
1666 | card->info.chpid); | 1663 | card->info.chpid); |
1667 | card->lan_online = 1; | ||
1668 | netif_carrier_on(card->dev); | 1664 | netif_carrier_on(card->dev); |
1669 | qeth_reset_ip_addresses(card); | 1665 | qeth_schedule_recovery(card); |
1670 | return NULL; | 1666 | return NULL; |
1667 | case IPA_CMD_MODCCID: | ||
1668 | return cmd; | ||
1671 | case IPA_CMD_REGISTER_LOCAL_ADDR: | 1669 | case IPA_CMD_REGISTER_LOCAL_ADDR: |
1672 | QETH_DBF_TEXT(trace,3, "irla"); | 1670 | QETH_DBF_TEXT(trace,3, "irla"); |
1673 | break; | 1671 | break; |
@@ -1729,6 +1727,14 @@ qeth_send_control_data_cb(struct qeth_channel *channel, | |||
1729 | cmd = qeth_check_ipa_data(card, iob); | 1727 | cmd = qeth_check_ipa_data(card, iob); |
1730 | if ((cmd == NULL) && (card->state != CARD_STATE_DOWN)) | 1728 | if ((cmd == NULL) && (card->state != CARD_STATE_DOWN)) |
1731 | goto out; | 1729 | goto out; |
1730 | /*in case of OSN : check if cmd is set */ | ||
1731 | if (card->info.type == QETH_CARD_TYPE_OSN && | ||
1732 | cmd && | ||
1733 | cmd->hdr.command != IPA_CMD_STARTLAN && | ||
1734 | card->osn_info.assist_cb != NULL) { | ||
1735 | card->osn_info.assist_cb(card->dev, cmd); | ||
1736 | goto out; | ||
1737 | } | ||
1732 | 1738 | ||
1733 | spin_lock_irqsave(&card->lock, flags); | 1739 | spin_lock_irqsave(&card->lock, flags); |
1734 | list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) { | 1740 | list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) { |
@@ -1745,8 +1751,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel, | |||
1745 | keep_reply = reply->callback(card, | 1751 | keep_reply = reply->callback(card, |
1746 | reply, | 1752 | reply, |
1747 | (unsigned long)cmd); | 1753 | (unsigned long)cmd); |
1748 | } | 1754 | } else |
1749 | else | ||
1750 | keep_reply = reply->callback(card, | 1755 | keep_reply = reply->callback(card, |
1751 | reply, | 1756 | reply, |
1752 | (unsigned long)iob); | 1757 | (unsigned long)iob); |
@@ -1776,6 +1781,24 @@ out: | |||
1776 | qeth_release_buffer(channel,iob); | 1781 | qeth_release_buffer(channel,iob); |
1777 | } | 1782 | } |
1778 | 1783 | ||
1784 | static inline void | ||
1785 | qeth_prepare_control_data(struct qeth_card *card, int len, | ||
1786 | struct qeth_cmd_buffer *iob) | ||
1787 | { | ||
1788 | qeth_setup_ccw(&card->write,iob->data,len); | ||
1789 | iob->callback = qeth_release_buffer; | ||
1790 | |||
1791 | memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data), | ||
1792 | &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH); | ||
1793 | card->seqno.trans_hdr++; | ||
1794 | memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data), | ||
1795 | &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH); | ||
1796 | card->seqno.pdu_hdr++; | ||
1797 | memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data), | ||
1798 | &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH); | ||
1799 | QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN); | ||
1800 | } | ||
1801 | |||
1779 | static int | 1802 | static int |
1780 | qeth_send_control_data(struct qeth_card *card, int len, | 1803 | qeth_send_control_data(struct qeth_card *card, int len, |
1781 | struct qeth_cmd_buffer *iob, | 1804 | struct qeth_cmd_buffer *iob, |
@@ -1786,24 +1809,11 @@ qeth_send_control_data(struct qeth_card *card, int len, | |||
1786 | { | 1809 | { |
1787 | int rc; | 1810 | int rc; |
1788 | unsigned long flags; | 1811 | unsigned long flags; |
1789 | struct qeth_reply *reply; | 1812 | struct qeth_reply *reply = NULL; |
1790 | struct timer_list timer; | 1813 | struct timer_list timer; |
1791 | 1814 | ||
1792 | QETH_DBF_TEXT(trace, 2, "sendctl"); | 1815 | QETH_DBF_TEXT(trace, 2, "sendctl"); |
1793 | 1816 | ||
1794 | qeth_setup_ccw(&card->write,iob->data,len); | ||
1795 | |||
1796 | memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data), | ||
1797 | &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH); | ||
1798 | card->seqno.trans_hdr++; | ||
1799 | |||
1800 | memcpy(QETH_PDU_HEADER_SEQ_NO(iob->data), | ||
1801 | &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH); | ||
1802 | card->seqno.pdu_hdr++; | ||
1803 | memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data), | ||
1804 | &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH); | ||
1805 | iob->callback = qeth_release_buffer; | ||
1806 | |||
1807 | reply = qeth_alloc_reply(card); | 1817 | reply = qeth_alloc_reply(card); |
1808 | if (!reply) { | 1818 | if (!reply) { |
1809 | PRINT_WARN("Could no alloc qeth_reply!\n"); | 1819 | PRINT_WARN("Could no alloc qeth_reply!\n"); |
@@ -1818,10 +1828,6 @@ qeth_send_control_data(struct qeth_card *card, int len, | |||
1818 | init_timer(&timer); | 1828 | init_timer(&timer); |
1819 | timer.function = qeth_cmd_timeout; | 1829 | timer.function = qeth_cmd_timeout; |
1820 | timer.data = (unsigned long) reply; | 1830 | timer.data = (unsigned long) reply; |
1821 | if (IS_IPA(iob->data)) | ||
1822 | timer.expires = jiffies + QETH_IPA_TIMEOUT; | ||
1823 | else | ||
1824 | timer.expires = jiffies + QETH_TIMEOUT; | ||
1825 | init_waitqueue_head(&reply->wait_q); | 1831 | init_waitqueue_head(&reply->wait_q); |
1826 | spin_lock_irqsave(&card->lock, flags); | 1832 | spin_lock_irqsave(&card->lock, flags); |
1827 | list_add_tail(&reply->list, &card->cmd_waiter_list); | 1833 | list_add_tail(&reply->list, &card->cmd_waiter_list); |
@@ -1829,6 +1835,11 @@ qeth_send_control_data(struct qeth_card *card, int len, | |||
1829 | QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN); | 1835 | QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN); |
1830 | wait_event(card->wait_q, | 1836 | wait_event(card->wait_q, |
1831 | atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0); | 1837 | atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0); |
1838 | qeth_prepare_control_data(card, len, iob); | ||
1839 | if (IS_IPA(iob->data)) | ||
1840 | timer.expires = jiffies + QETH_IPA_TIMEOUT; | ||
1841 | else | ||
1842 | timer.expires = jiffies + QETH_TIMEOUT; | ||
1832 | QETH_DBF_TEXT(trace, 6, "noirqpnd"); | 1843 | QETH_DBF_TEXT(trace, 6, "noirqpnd"); |
1833 | spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); | 1844 | spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); |
1834 | rc = ccw_device_start(card->write.ccwdev, &card->write.ccw, | 1845 | rc = ccw_device_start(card->write.ccwdev, &card->write.ccw, |
@@ -1856,6 +1867,62 @@ qeth_send_control_data(struct qeth_card *card, int len, | |||
1856 | } | 1867 | } |
1857 | 1868 | ||
1858 | static int | 1869 | static int |
1870 | qeth_osn_send_control_data(struct qeth_card *card, int len, | ||
1871 | struct qeth_cmd_buffer *iob) | ||
1872 | { | ||
1873 | unsigned long flags; | ||
1874 | int rc = 0; | ||
1875 | |||
1876 | QETH_DBF_TEXT(trace, 5, "osndctrd"); | ||
1877 | |||
1878 | wait_event(card->wait_q, | ||
1879 | atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0); | ||
1880 | qeth_prepare_control_data(card, len, iob); | ||
1881 | QETH_DBF_TEXT(trace, 6, "osnoirqp"); | ||
1882 | spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); | ||
1883 | rc = ccw_device_start(card->write.ccwdev, &card->write.ccw, | ||
1884 | (addr_t) iob, 0, 0); | ||
1885 | spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags); | ||
1886 | if (rc){ | ||
1887 | PRINT_WARN("qeth_osn_send_control_data: " | ||
1888 | "ccw_device_start rc = %i\n", rc); | ||
1889 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); | ||
1890 | qeth_release_buffer(iob->channel, iob); | ||
1891 | atomic_set(&card->write.irq_pending, 0); | ||
1892 | wake_up(&card->wait_q); | ||
1893 | } | ||
1894 | return rc; | ||
1895 | } | ||
1896 | |||
1897 | static inline void | ||
1898 | qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, | ||
1899 | char prot_type) | ||
1900 | { | ||
1901 | memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE); | ||
1902 | memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1); | ||
1903 | memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data), | ||
1904 | &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH); | ||
1905 | } | ||
1906 | |||
1907 | static int | ||
1908 | qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, | ||
1909 | int data_len) | ||
1910 | { | ||
1911 | u16 s1, s2; | ||
1912 | |||
1913 | QETH_DBF_TEXT(trace,4,"osndipa"); | ||
1914 | |||
1915 | qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2); | ||
1916 | s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len); | ||
1917 | s2 = (u16)data_len; | ||
1918 | memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2); | ||
1919 | memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2); | ||
1920 | memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2); | ||
1921 | memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2); | ||
1922 | return qeth_osn_send_control_data(card, s1, iob); | ||
1923 | } | ||
1924 | |||
1925 | static int | ||
1859 | qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, | 1926 | qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, |
1860 | int (*reply_cb) | 1927 | int (*reply_cb) |
1861 | (struct qeth_card *,struct qeth_reply*, unsigned long), | 1928 | (struct qeth_card *,struct qeth_reply*, unsigned long), |
@@ -1866,17 +1933,14 @@ qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, | |||
1866 | 1933 | ||
1867 | QETH_DBF_TEXT(trace,4,"sendipa"); | 1934 | QETH_DBF_TEXT(trace,4,"sendipa"); |
1868 | 1935 | ||
1869 | memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE); | ||
1870 | |||
1871 | if (card->options.layer2) | 1936 | if (card->options.layer2) |
1872 | prot_type = QETH_PROT_LAYER2; | 1937 | if (card->info.type == QETH_CARD_TYPE_OSN) |
1938 | prot_type = QETH_PROT_OSN2; | ||
1939 | else | ||
1940 | prot_type = QETH_PROT_LAYER2; | ||
1873 | else | 1941 | else |
1874 | prot_type = QETH_PROT_TCPIP; | 1942 | prot_type = QETH_PROT_TCPIP; |
1875 | 1943 | qeth_prepare_ipa_cmd(card,iob,prot_type); | |
1876 | memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data),&prot_type,1); | ||
1877 | memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data), | ||
1878 | &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH); | ||
1879 | |||
1880 | rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob, | 1944 | rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob, |
1881 | reply_cb, reply_param); | 1945 | reply_cb, reply_param); |
1882 | return rc; | 1946 | return rc; |
@@ -2018,7 +2082,10 @@ qeth_ulp_enable(struct qeth_card *card) | |||
2018 | *(QETH_ULP_ENABLE_LINKNUM(iob->data)) = | 2082 | *(QETH_ULP_ENABLE_LINKNUM(iob->data)) = |
2019 | (__u8) card->info.portno; | 2083 | (__u8) card->info.portno; |
2020 | if (card->options.layer2) | 2084 | if (card->options.layer2) |
2021 | prot_type = QETH_PROT_LAYER2; | 2085 | if (card->info.type == QETH_CARD_TYPE_OSN) |
2086 | prot_type = QETH_PROT_OSN2; | ||
2087 | else | ||
2088 | prot_type = QETH_PROT_LAYER2; | ||
2022 | else | 2089 | else |
2023 | prot_type = QETH_PROT_TCPIP; | 2090 | prot_type = QETH_PROT_TCPIP; |
2024 | 2091 | ||
@@ -2108,15 +2175,21 @@ qeth_check_for_inbound_error(struct qeth_qdio_buffer *buf, | |||
2108 | } | 2175 | } |
2109 | 2176 | ||
2110 | static inline struct sk_buff * | 2177 | static inline struct sk_buff * |
2111 | qeth_get_skb(unsigned int length) | 2178 | qeth_get_skb(unsigned int length, struct qeth_hdr *hdr) |
2112 | { | 2179 | { |
2113 | struct sk_buff* skb; | 2180 | struct sk_buff* skb; |
2181 | int add_len; | ||
2182 | |||
2183 | add_len = 0; | ||
2184 | if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN) | ||
2185 | add_len = sizeof(struct qeth_hdr); | ||
2114 | #ifdef CONFIG_QETH_VLAN | 2186 | #ifdef CONFIG_QETH_VLAN |
2115 | if ((skb = dev_alloc_skb(length + VLAN_HLEN))) | 2187 | else |
2116 | skb_reserve(skb, VLAN_HLEN); | 2188 | add_len = VLAN_HLEN; |
2117 | #else | ||
2118 | skb = dev_alloc_skb(length); | ||
2119 | #endif | 2189 | #endif |
2190 | skb = dev_alloc_skb(length + add_len); | ||
2191 | if (skb && add_len) | ||
2192 | skb_reserve(skb, add_len); | ||
2120 | return skb; | 2193 | return skb; |
2121 | } | 2194 | } |
2122 | 2195 | ||
@@ -2146,7 +2219,10 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, | |||
2146 | 2219 | ||
2147 | offset += sizeof(struct qeth_hdr); | 2220 | offset += sizeof(struct qeth_hdr); |
2148 | if (card->options.layer2) | 2221 | if (card->options.layer2) |
2149 | skb_len = (*hdr)->hdr.l2.pkt_length; | 2222 | if (card->info.type == QETH_CARD_TYPE_OSN) |
2223 | skb_len = (*hdr)->hdr.osn.pdu_length; | ||
2224 | else | ||
2225 | skb_len = (*hdr)->hdr.l2.pkt_length; | ||
2150 | else | 2226 | else |
2151 | skb_len = (*hdr)->hdr.l3.length; | 2227 | skb_len = (*hdr)->hdr.l3.length; |
2152 | 2228 | ||
@@ -2154,15 +2230,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, | |||
2154 | return NULL; | 2230 | return NULL; |
2155 | if (card->options.fake_ll){ | 2231 | if (card->options.fake_ll){ |
2156 | if(card->dev->type == ARPHRD_IEEE802_TR){ | 2232 | if(card->dev->type == ARPHRD_IEEE802_TR){ |
2157 | if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR))) | 2233 | if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr))) |
2158 | goto no_mem; | 2234 | goto no_mem; |
2159 | skb_reserve(skb,QETH_FAKE_LL_LEN_TR); | 2235 | skb_reserve(skb,QETH_FAKE_LL_LEN_TR); |
2160 | } else { | 2236 | } else { |
2161 | if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH))) | 2237 | if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr))) |
2162 | goto no_mem; | 2238 | goto no_mem; |
2163 | skb_reserve(skb,QETH_FAKE_LL_LEN_ETH); | 2239 | skb_reserve(skb,QETH_FAKE_LL_LEN_ETH); |
2164 | } | 2240 | } |
2165 | } else if (!(skb = qeth_get_skb(skb_len))) | 2241 | } else if (!(skb = qeth_get_skb(skb_len, *hdr))) |
2166 | goto no_mem; | 2242 | goto no_mem; |
2167 | data_ptr = element->addr + offset; | 2243 | data_ptr = element->addr + offset; |
2168 | while (skb_len) { | 2244 | while (skb_len) { |
@@ -2387,6 +2463,7 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | |||
2387 | skb_pull(skb, VLAN_HLEN); | 2463 | skb_pull(skb, VLAN_HLEN); |
2388 | } | 2464 | } |
2389 | #endif | 2465 | #endif |
2466 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; | ||
2390 | return vlan_id; | 2467 | return vlan_id; |
2391 | } | 2468 | } |
2392 | 2469 | ||
@@ -2460,8 +2537,12 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
2460 | skb->dev = card->dev; | 2537 | skb->dev = card->dev; |
2461 | if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) | 2538 | if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) |
2462 | vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); | 2539 | vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); |
2463 | else | 2540 | else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) |
2464 | qeth_rebuild_skb(card, skb, hdr); | 2541 | qeth_rebuild_skb(card, skb, hdr); |
2542 | else { /*in case of OSN*/ | ||
2543 | skb_push(skb, sizeof(struct qeth_hdr)); | ||
2544 | memcpy(skb->data, hdr, sizeof(struct qeth_hdr)); | ||
2545 | } | ||
2465 | /* is device UP ? */ | 2546 | /* is device UP ? */ |
2466 | if (!(card->dev->flags & IFF_UP)){ | 2547 | if (!(card->dev->flags & IFF_UP)){ |
2467 | dev_kfree_skb_any(skb); | 2548 | dev_kfree_skb_any(skb); |
@@ -2472,7 +2553,10 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
2472 | vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); | 2553 | vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); |
2473 | else | 2554 | else |
2474 | #endif | 2555 | #endif |
2475 | rxrc = netif_rx(skb); | 2556 | if (card->info.type == QETH_CARD_TYPE_OSN) |
2557 | rxrc = card->osn_info.data_cb(skb); | ||
2558 | else | ||
2559 | rxrc = netif_rx(skb); | ||
2476 | card->dev->last_rx = jiffies; | 2560 | card->dev->last_rx = jiffies; |
2477 | card->stats.rx_packets++; | 2561 | card->stats.rx_packets++; |
2478 | card->stats.rx_bytes += skb->len; | 2562 | card->stats.rx_bytes += skb->len; |
@@ -3014,7 +3098,7 @@ qeth_alloc_buffer_pool(struct qeth_card *card) | |||
3014 | return -ENOMEM; | 3098 | return -ENOMEM; |
3015 | } | 3099 | } |
3016 | for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){ | 3100 | for(j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j){ |
3017 | ptr = (void *) __get_free_page(GFP_KERNEL); | 3101 | ptr = (void *) __get_free_page(GFP_KERNEL|GFP_DMA); |
3018 | if (!ptr) { | 3102 | if (!ptr) { |
3019 | while (j > 0) | 3103 | while (j > 0) |
3020 | free_page((unsigned long) | 3104 | free_page((unsigned long) |
@@ -3058,7 +3142,8 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
3058 | if (card->qdio.state == QETH_QDIO_ALLOCATED) | 3142 | if (card->qdio.state == QETH_QDIO_ALLOCATED) |
3059 | return 0; | 3143 | return 0; |
3060 | 3144 | ||
3061 | card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), GFP_KERNEL); | 3145 | card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), |
3146 | GFP_KERNEL|GFP_DMA); | ||
3062 | if (!card->qdio.in_q) | 3147 | if (!card->qdio.in_q) |
3063 | return - ENOMEM; | 3148 | return - ENOMEM; |
3064 | QETH_DBF_TEXT(setup, 2, "inq"); | 3149 | QETH_DBF_TEXT(setup, 2, "inq"); |
@@ -3083,7 +3168,7 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
3083 | } | 3168 | } |
3084 | for (i = 0; i < card->qdio.no_out_queues; ++i){ | 3169 | for (i = 0; i < card->qdio.no_out_queues; ++i){ |
3085 | card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), | 3170 | card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), |
3086 | GFP_KERNEL); | 3171 | GFP_KERNEL|GFP_DMA); |
3087 | if (!card->qdio.out_qs[i]){ | 3172 | if (!card->qdio.out_qs[i]){ |
3088 | while (i > 0) | 3173 | while (i > 0) |
3089 | kfree(card->qdio.out_qs[--i]); | 3174 | kfree(card->qdio.out_qs[--i]); |
@@ -3156,8 +3241,6 @@ qeth_init_qdio_info(struct qeth_card *card) | |||
3156 | INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list); | 3241 | INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list); |
3157 | INIT_LIST_HEAD(&card->qdio.init_pool.entry_list); | 3242 | INIT_LIST_HEAD(&card->qdio.init_pool.entry_list); |
3158 | /* outbound */ | 3243 | /* outbound */ |
3159 | card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; | ||
3160 | card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; | ||
3161 | } | 3244 | } |
3162 | 3245 | ||
3163 | static int | 3246 | static int |
@@ -3472,7 +3555,7 @@ qeth_mpc_initialize(struct qeth_card *card) | |||
3472 | 3555 | ||
3473 | return 0; | 3556 | return 0; |
3474 | out_qdio: | 3557 | out_qdio: |
3475 | qeth_qdio_clear_card(card, card->info.type==QETH_CARD_TYPE_OSAE); | 3558 | qeth_qdio_clear_card(card, card->info.type!=QETH_CARD_TYPE_IQD); |
3476 | return rc; | 3559 | return rc; |
3477 | } | 3560 | } |
3478 | 3561 | ||
@@ -3497,6 +3580,9 @@ qeth_get_netdevice(enum qeth_card_types type, enum qeth_link_types linktype) | |||
3497 | case QETH_CARD_TYPE_IQD: | 3580 | case QETH_CARD_TYPE_IQD: |
3498 | dev = alloc_netdev(0, "hsi%d", ether_setup); | 3581 | dev = alloc_netdev(0, "hsi%d", ether_setup); |
3499 | break; | 3582 | break; |
3583 | case QETH_CARD_TYPE_OSN: | ||
3584 | dev = alloc_netdev(0, "osn%d", ether_setup); | ||
3585 | break; | ||
3500 | default: | 3586 | default: |
3501 | dev = alloc_etherdev(0); | 3587 | dev = alloc_etherdev(0); |
3502 | } | 3588 | } |
@@ -3661,7 +3747,8 @@ qeth_open(struct net_device *dev) | |||
3661 | if (card->state != CARD_STATE_SOFTSETUP) | 3747 | if (card->state != CARD_STATE_SOFTSETUP) |
3662 | return -ENODEV; | 3748 | return -ENODEV; |
3663 | 3749 | ||
3664 | if ( (card->options.layer2) && | 3750 | if ( (card->info.type != QETH_CARD_TYPE_OSN) && |
3751 | (card->options.layer2) && | ||
3665 | (!card->info.layer2_mac_registered)) { | 3752 | (!card->info.layer2_mac_registered)) { |
3666 | QETH_DBF_TEXT(trace,4,"nomacadr"); | 3753 | QETH_DBF_TEXT(trace,4,"nomacadr"); |
3667 | return -EPERM; | 3754 | return -EPERM; |
@@ -3699,6 +3786,9 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) | |||
3699 | { | 3786 | { |
3700 | int cast_type = RTN_UNSPEC; | 3787 | int cast_type = RTN_UNSPEC; |
3701 | 3788 | ||
3789 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
3790 | return cast_type; | ||
3791 | |||
3702 | if (skb->dst && skb->dst->neighbour){ | 3792 | if (skb->dst && skb->dst->neighbour){ |
3703 | cast_type = skb->dst->neighbour->type; | 3793 | cast_type = skb->dst->neighbour->type; |
3704 | if ((cast_type == RTN_BROADCAST) || | 3794 | if ((cast_type == RTN_BROADCAST) || |
@@ -3788,13 +3878,16 @@ static inline int | |||
3788 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, | 3878 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, |
3789 | struct qeth_hdr **hdr, int ipv) | 3879 | struct qeth_hdr **hdr, int ipv) |
3790 | { | 3880 | { |
3791 | int rc; | 3881 | int rc = 0; |
3792 | #ifdef CONFIG_QETH_VLAN | 3882 | #ifdef CONFIG_QETH_VLAN |
3793 | u16 *tag; | 3883 | u16 *tag; |
3794 | #endif | 3884 | #endif |
3795 | 3885 | ||
3796 | QETH_DBF_TEXT(trace, 6, "prepskb"); | 3886 | QETH_DBF_TEXT(trace, 6, "prepskb"); |
3797 | 3887 | if (card->info.type == QETH_CARD_TYPE_OSN) { | |
3888 | *hdr = (struct qeth_hdr *)(*skb)->data; | ||
3889 | return rc; | ||
3890 | } | ||
3798 | rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); | 3891 | rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); |
3799 | if (rc) | 3892 | if (rc) |
3800 | return rc; | 3893 | return rc; |
@@ -4297,8 +4390,14 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
4297 | } | 4390 | } |
4298 | } | 4391 | } |
4299 | } | 4392 | } |
4393 | if ((card->info.type == QETH_CARD_TYPE_OSN) && | ||
4394 | (skb->protocol == htons(ETH_P_IPV6))) { | ||
4395 | dev_kfree_skb_any(skb); | ||
4396 | return 0; | ||
4397 | } | ||
4300 | cast_type = qeth_get_cast_type(card, skb); | 4398 | cast_type = qeth_get_cast_type(card, skb); |
4301 | if ((cast_type == RTN_BROADCAST) && (card->info.broadcast_capable == 0)){ | 4399 | if ((cast_type == RTN_BROADCAST) && |
4400 | (card->info.broadcast_capable == 0)){ | ||
4302 | card->stats.tx_dropped++; | 4401 | card->stats.tx_dropped++; |
4303 | card->stats.tx_errors++; | 4402 | card->stats.tx_errors++; |
4304 | dev_kfree_skb_any(skb); | 4403 | dev_kfree_skb_any(skb); |
@@ -4326,7 +4425,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
4326 | QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); | 4425 | QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); |
4327 | return rc; | 4426 | return rc; |
4328 | } | 4427 | } |
4329 | qeth_fill_header(card, hdr, skb, ipv, cast_type); | 4428 | if (card->info.type != QETH_CARD_TYPE_OSN) |
4429 | qeth_fill_header(card, hdr, skb, ipv, cast_type); | ||
4330 | } | 4430 | } |
4331 | 4431 | ||
4332 | if (large_send == QETH_LARGE_SEND_EDDP) { | 4432 | if (large_send == QETH_LARGE_SEND_EDDP) { |
@@ -4387,6 +4487,7 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum) | |||
4387 | case MII_BMCR: /* Basic mode control register */ | 4487 | case MII_BMCR: /* Basic mode control register */ |
4388 | rc = BMCR_FULLDPLX; | 4488 | rc = BMCR_FULLDPLX; |
4389 | if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&& | 4489 | if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH)&& |
4490 | (card->info.link_type != QETH_LINK_TYPE_OSN) && | ||
4390 | (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH)) | 4491 | (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH)) |
4391 | rc |= BMCR_SPEED100; | 4492 | rc |= BMCR_SPEED100; |
4392 | break; | 4493 | break; |
@@ -5010,6 +5111,9 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
5010 | (card->state != CARD_STATE_SOFTSETUP)) | 5111 | (card->state != CARD_STATE_SOFTSETUP)) |
5011 | return -ENODEV; | 5112 | return -ENODEV; |
5012 | 5113 | ||
5114 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
5115 | return -EPERM; | ||
5116 | |||
5013 | switch (cmd){ | 5117 | switch (cmd){ |
5014 | case SIOC_QETH_ARP_SET_NO_ENTRIES: | 5118 | case SIOC_QETH_ARP_SET_NO_ENTRIES: |
5015 | if ( !capable(CAP_NET_ADMIN) || | 5119 | if ( !capable(CAP_NET_ADMIN) || |
@@ -5200,7 +5304,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) | |||
5200 | if (!card->vlangrp) | 5304 | if (!card->vlangrp) |
5201 | return; | 5305 | return; |
5202 | rcu_read_lock(); | 5306 | rcu_read_lock(); |
5203 | in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]); | 5307 | in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); |
5204 | if (!in_dev) | 5308 | if (!in_dev) |
5205 | goto out; | 5309 | goto out; |
5206 | for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { | 5310 | for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { |
@@ -5335,6 +5439,9 @@ qeth_set_multicast_list(struct net_device *dev) | |||
5335 | { | 5439 | { |
5336 | struct qeth_card *card = (struct qeth_card *) dev->priv; | 5440 | struct qeth_card *card = (struct qeth_card *) dev->priv; |
5337 | 5441 | ||
5442 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
5443 | return ; | ||
5444 | |||
5338 | QETH_DBF_TEXT(trace,3,"setmulti"); | 5445 | QETH_DBF_TEXT(trace,3,"setmulti"); |
5339 | qeth_delete_mc_addresses(card); | 5446 | qeth_delete_mc_addresses(card); |
5340 | qeth_add_multicast_ipv4(card); | 5447 | qeth_add_multicast_ipv4(card); |
@@ -5376,6 +5483,94 @@ qeth_get_addr_buffer(enum qeth_prot_versions prot) | |||
5376 | return addr; | 5483 | return addr; |
5377 | } | 5484 | } |
5378 | 5485 | ||
5486 | int | ||
5487 | qeth_osn_assist(struct net_device *dev, | ||
5488 | void *data, | ||
5489 | int data_len) | ||
5490 | { | ||
5491 | struct qeth_cmd_buffer *iob; | ||
5492 | struct qeth_card *card; | ||
5493 | int rc; | ||
5494 | |||
5495 | QETH_DBF_TEXT(trace, 2, "osnsdmc"); | ||
5496 | if (!dev) | ||
5497 | return -ENODEV; | ||
5498 | card = (struct qeth_card *)dev->priv; | ||
5499 | if (!card) | ||
5500 | return -ENODEV; | ||
5501 | if ((card->state != CARD_STATE_UP) && | ||
5502 | (card->state != CARD_STATE_SOFTSETUP)) | ||
5503 | return -ENODEV; | ||
5504 | iob = qeth_wait_for_buffer(&card->write); | ||
5505 | memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len); | ||
5506 | rc = qeth_osn_send_ipa_cmd(card, iob, data_len); | ||
5507 | return rc; | ||
5508 | } | ||
5509 | |||
5510 | static struct net_device * | ||
5511 | qeth_netdev_by_devno(unsigned char *read_dev_no) | ||
5512 | { | ||
5513 | struct qeth_card *card; | ||
5514 | struct net_device *ndev; | ||
5515 | unsigned char *readno; | ||
5516 | __u16 temp_dev_no, card_dev_no; | ||
5517 | char *endp; | ||
5518 | unsigned long flags; | ||
5519 | |||
5520 | ndev = NULL; | ||
5521 | memcpy(&temp_dev_no, read_dev_no, 2); | ||
5522 | read_lock_irqsave(&qeth_card_list.rwlock, flags); | ||
5523 | list_for_each_entry(card, &qeth_card_list.list, list) { | ||
5524 | readno = CARD_RDEV_ID(card); | ||
5525 | readno += (strlen(readno) - 4); | ||
5526 | card_dev_no = simple_strtoul(readno, &endp, 16); | ||
5527 | if (card_dev_no == temp_dev_no) { | ||
5528 | ndev = card->dev; | ||
5529 | break; | ||
5530 | } | ||
5531 | } | ||
5532 | read_unlock_irqrestore(&qeth_card_list.rwlock, flags); | ||
5533 | return ndev; | ||
5534 | } | ||
5535 | |||
5536 | int | ||
5537 | qeth_osn_register(unsigned char *read_dev_no, | ||
5538 | struct net_device **dev, | ||
5539 | int (*assist_cb)(struct net_device *, void *), | ||
5540 | int (*data_cb)(struct sk_buff *)) | ||
5541 | { | ||
5542 | struct qeth_card * card; | ||
5543 | |||
5544 | QETH_DBF_TEXT(trace, 2, "osnreg"); | ||
5545 | *dev = qeth_netdev_by_devno(read_dev_no); | ||
5546 | if (*dev == NULL) | ||
5547 | return -ENODEV; | ||
5548 | card = (struct qeth_card *)(*dev)->priv; | ||
5549 | if (!card) | ||
5550 | return -ENODEV; | ||
5551 | if ((assist_cb == NULL) || (data_cb == NULL)) | ||
5552 | return -EINVAL; | ||
5553 | card->osn_info.assist_cb = assist_cb; | ||
5554 | card->osn_info.data_cb = data_cb; | ||
5555 | return 0; | ||
5556 | } | ||
5557 | |||
5558 | void | ||
5559 | qeth_osn_deregister(struct net_device * dev) | ||
5560 | { | ||
5561 | struct qeth_card *card; | ||
5562 | |||
5563 | QETH_DBF_TEXT(trace, 2, "osndereg"); | ||
5564 | if (!dev) | ||
5565 | return; | ||
5566 | card = (struct qeth_card *)dev->priv; | ||
5567 | if (!card) | ||
5568 | return; | ||
5569 | card->osn_info.assist_cb = NULL; | ||
5570 | card->osn_info.data_cb = NULL; | ||
5571 | return; | ||
5572 | } | ||
5573 | |||
5379 | static void | 5574 | static void |
5380 | qeth_delete_mc_addresses(struct qeth_card *card) | 5575 | qeth_delete_mc_addresses(struct qeth_card *card) |
5381 | { | 5576 | { |
@@ -5706,6 +5901,12 @@ qeth_layer2_set_mac_address(struct net_device *dev, void *p) | |||
5706 | QETH_DBF_TEXT(trace, 3, "setmcLY3"); | 5901 | QETH_DBF_TEXT(trace, 3, "setmcLY3"); |
5707 | return -EOPNOTSUPP; | 5902 | return -EOPNOTSUPP; |
5708 | } | 5903 | } |
5904 | if (card->info.type == QETH_CARD_TYPE_OSN) { | ||
5905 | PRINT_WARN("Setting MAC address on %s is not supported.\n", | ||
5906 | dev->name); | ||
5907 | QETH_DBF_TEXT(trace, 3, "setmcOSN"); | ||
5908 | return -EOPNOTSUPP; | ||
5909 | } | ||
5709 | QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card)); | 5910 | QETH_DBF_TEXT_(trace, 3, "%s", CARD_BUS_ID(card)); |
5710 | QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN); | 5911 | QETH_DBF_HEX(trace, 3, addr->sa_data, OSA_ADDR_LEN); |
5711 | rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]); | 5912 | rc = qeth_layer2_send_delmac(card, &card->dev->dev_addr[0]); |
@@ -6082,9 +6283,8 @@ qeth_netdev_init(struct net_device *dev) | |||
6082 | qeth_get_hlen(card->info.link_type) + card->options.add_hhlen; | 6283 | qeth_get_hlen(card->info.link_type) + card->options.add_hhlen; |
6083 | dev->addr_len = OSA_ADDR_LEN; | 6284 | dev->addr_len = OSA_ADDR_LEN; |
6084 | dev->mtu = card->info.initial_mtu; | 6285 | dev->mtu = card->info.initial_mtu; |
6085 | 6286 | if (card->info.type != QETH_CARD_TYPE_OSN) | |
6086 | SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops); | 6287 | SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops); |
6087 | |||
6088 | SET_MODULE_OWNER(dev); | 6288 | SET_MODULE_OWNER(dev); |
6089 | return 0; | 6289 | return 0; |
6090 | } | 6290 | } |
@@ -6101,6 +6301,7 @@ qeth_init_func_level(struct qeth_card *card) | |||
6101 | QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT; | 6301 | QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT; |
6102 | } else { | 6302 | } else { |
6103 | if (card->info.type == QETH_CARD_TYPE_IQD) | 6303 | if (card->info.type == QETH_CARD_TYPE_IQD) |
6304 | /*FIXME:why do we have same values for dis and ena for osae??? */ | ||
6104 | card->info.func_level = | 6305 | card->info.func_level = |
6105 | QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT; | 6306 | QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT; |
6106 | else | 6307 | else |
@@ -6130,7 +6331,7 @@ retry: | |||
6130 | ccw_device_set_online(CARD_WDEV(card)); | 6331 | ccw_device_set_online(CARD_WDEV(card)); |
6131 | ccw_device_set_online(CARD_DDEV(card)); | 6332 | ccw_device_set_online(CARD_DDEV(card)); |
6132 | } | 6333 | } |
6133 | rc = qeth_qdio_clear_card(card,card->info.type==QETH_CARD_TYPE_OSAE); | 6334 | rc = qeth_qdio_clear_card(card,card->info.type!=QETH_CARD_TYPE_IQD); |
6134 | if (rc == -ERESTARTSYS) { | 6335 | if (rc == -ERESTARTSYS) { |
6135 | QETH_DBF_TEXT(setup, 2, "break1"); | 6336 | QETH_DBF_TEXT(setup, 2, "break1"); |
6136 | return rc; | 6337 | return rc; |
@@ -6182,8 +6383,8 @@ retry: | |||
6182 | card->dev = qeth_get_netdevice(card->info.type, | 6383 | card->dev = qeth_get_netdevice(card->info.type, |
6183 | card->info.link_type); | 6384 | card->info.link_type); |
6184 | if (!card->dev){ | 6385 | if (!card->dev){ |
6185 | qeth_qdio_clear_card(card, card->info.type == | 6386 | qeth_qdio_clear_card(card, card->info.type != |
6186 | QETH_CARD_TYPE_OSAE); | 6387 | QETH_CARD_TYPE_IQD); |
6187 | rc = -ENODEV; | 6388 | rc = -ENODEV; |
6188 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); | 6389 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); |
6189 | goto out; | 6390 | goto out; |
@@ -6470,6 +6671,9 @@ qeth_query_ipassists_cb(struct qeth_card *card, struct qeth_reply *reply, | |||
6470 | if (cmd->hdr.prot_version == QETH_PROT_IPV4) { | 6671 | if (cmd->hdr.prot_version == QETH_PROT_IPV4) { |
6471 | card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; | 6672 | card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; |
6472 | card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; | 6673 | card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; |
6674 | /* Disable IPV6 support hard coded for Hipersockets */ | ||
6675 | if(card->info.type == QETH_CARD_TYPE_IQD) | ||
6676 | card->options.ipa4.supported_funcs &= ~IPA_IPV6; | ||
6473 | } else { | 6677 | } else { |
6474 | #ifdef CONFIG_QETH_IPV6 | 6678 | #ifdef CONFIG_QETH_IPV6 |
6475 | card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; | 6679 | card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; |
@@ -7087,6 +7291,8 @@ qeth_softsetup_card(struct qeth_card *card) | |||
7087 | return rc; | 7291 | return rc; |
7088 | } else | 7292 | } else |
7089 | card->lan_online = 1; | 7293 | card->lan_online = 1; |
7294 | if (card->info.type==QETH_CARD_TYPE_OSN) | ||
7295 | goto out; | ||
7090 | if (card->options.layer2) { | 7296 | if (card->options.layer2) { |
7091 | card->dev->features |= | 7297 | card->dev->features |= |
7092 | NETIF_F_HW_VLAN_FILTER | | 7298 | NETIF_F_HW_VLAN_FILTER | |
@@ -7258,7 +7464,8 @@ qeth_stop_card(struct qeth_card *card, int recovery_mode) | |||
7258 | if (card->read.state == CH_STATE_UP && | 7464 | if (card->read.state == CH_STATE_UP && |
7259 | card->write.state == CH_STATE_UP && | 7465 | card->write.state == CH_STATE_UP && |
7260 | (card->state == CARD_STATE_UP)) { | 7466 | (card->state == CARD_STATE_UP)) { |
7261 | if(recovery_mode) { | 7467 | if (recovery_mode && |
7468 | card->info.type != QETH_CARD_TYPE_OSN) { | ||
7262 | qeth_stop(card->dev); | 7469 | qeth_stop(card->dev); |
7263 | } else { | 7470 | } else { |
7264 | rtnl_lock(); | 7471 | rtnl_lock(); |
@@ -7440,7 +7647,8 @@ qeth_start_again(struct qeth_card *card, int recovery_mode) | |||
7440 | { | 7647 | { |
7441 | QETH_DBF_TEXT(setup ,2, "startag"); | 7648 | QETH_DBF_TEXT(setup ,2, "startag"); |
7442 | 7649 | ||
7443 | if(recovery_mode) { | 7650 | if (recovery_mode && |
7651 | card->info.type != QETH_CARD_TYPE_OSN) { | ||
7444 | qeth_open(card->dev); | 7652 | qeth_open(card->dev); |
7445 | } else { | 7653 | } else { |
7446 | rtnl_lock(); | 7654 | rtnl_lock(); |
@@ -7472,33 +7680,36 @@ qeth_start_again(struct qeth_card *card, int recovery_mode) | |||
7472 | static void qeth_make_parameters_consistent(struct qeth_card *card) | 7680 | static void qeth_make_parameters_consistent(struct qeth_card *card) |
7473 | { | 7681 | { |
7474 | 7682 | ||
7475 | if (card->options.layer2) { | 7683 | if (card->options.layer2 == 0) |
7476 | if (card->info.type == QETH_CARD_TYPE_IQD) { | 7684 | return; |
7477 | PRINT_ERR("Device %s does not support " \ | 7685 | if (card->info.type == QETH_CARD_TYPE_OSN) |
7478 | "layer 2 functionality. " \ | 7686 | return; |
7479 | "Ignoring layer2 option.\n",CARD_BUS_ID(card)); | 7687 | if (card->info.type == QETH_CARD_TYPE_IQD) { |
7480 | } | 7688 | PRINT_ERR("Device %s does not support layer 2 functionality." \ |
7481 | IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER, | 7689 | " Ignoring layer2 option.\n",CARD_BUS_ID(card)); |
7482 | "Routing options are"); | 7690 | card->options.layer2 = 0; |
7691 | return; | ||
7692 | } | ||
7693 | IGNORE_PARAM_NEQ(route4.type, NO_ROUTER, NO_ROUTER, | ||
7694 | "Routing options are"); | ||
7483 | #ifdef CONFIG_QETH_IPV6 | 7695 | #ifdef CONFIG_QETH_IPV6 |
7484 | IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER, | 7696 | IGNORE_PARAM_NEQ(route6.type, NO_ROUTER, NO_ROUTER, |
7485 | "Routing options are"); | 7697 | "Routing options are"); |
7486 | #endif | 7698 | #endif |
7487 | IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING, | 7699 | IGNORE_PARAM_EQ(checksum_type, HW_CHECKSUMMING, |
7488 | QETH_CHECKSUM_DEFAULT, | 7700 | QETH_CHECKSUM_DEFAULT, |
7489 | "Checksumming options are"); | 7701 | "Checksumming options are"); |
7490 | IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS, | 7702 | IGNORE_PARAM_NEQ(broadcast_mode, QETH_TR_BROADCAST_ALLRINGS, |
7491 | QETH_TR_BROADCAST_ALLRINGS, | 7703 | QETH_TR_BROADCAST_ALLRINGS, |
7492 | "Broadcast mode options are"); | 7704 | "Broadcast mode options are"); |
7493 | IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL, | 7705 | IGNORE_PARAM_NEQ(macaddr_mode, QETH_TR_MACADDR_NONCANONICAL, |
7494 | QETH_TR_MACADDR_NONCANONICAL, | 7706 | QETH_TR_MACADDR_NONCANONICAL, |
7495 | "Canonical MAC addr options are"); | 7707 | "Canonical MAC addr options are"); |
7496 | IGNORE_PARAM_NEQ(fake_broadcast, 0, 0, | 7708 | IGNORE_PARAM_NEQ(fake_broadcast, 0, 0, |
7497 | "Broadcast faking options are"); | 7709 | "Broadcast faking options are"); |
7498 | IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN, | 7710 | IGNORE_PARAM_NEQ(add_hhlen, DEFAULT_ADD_HHLEN, |
7499 | DEFAULT_ADD_HHLEN,"Option add_hhlen is"); | 7711 | DEFAULT_ADD_HHLEN,"Option add_hhlen is"); |
7500 | IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is"); | 7712 | IGNORE_PARAM_NEQ(fake_ll, 0, 0,"Option fake_ll is"); |
7501 | } | ||
7502 | } | 7713 | } |
7503 | 7714 | ||
7504 | 7715 | ||
@@ -7528,8 +7739,7 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
7528 | return -EIO; | 7739 | return -EIO; |
7529 | } | 7740 | } |
7530 | 7741 | ||
7531 | if (card->options.layer2) | 7742 | qeth_make_parameters_consistent(card); |
7532 | qeth_make_parameters_consistent(card); | ||
7533 | 7743 | ||
7534 | if ((rc = qeth_hardsetup_card(card))){ | 7744 | if ((rc = qeth_hardsetup_card(card))){ |
7535 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); | 7745 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); |
@@ -7588,6 +7798,7 @@ qeth_set_online(struct ccwgroup_device *gdev) | |||
7588 | static struct ccw_device_id qeth_ids[] = { | 7798 | static struct ccw_device_id qeth_ids[] = { |
7589 | {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE}, | 7799 | {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE}, |
7590 | {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD}, | 7800 | {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD}, |
7801 | {CCW_DEVICE(0x1731, 0x06), driver_info:QETH_CARD_TYPE_OSN}, | ||
7591 | {}, | 7802 | {}, |
7592 | }; | 7803 | }; |
7593 | MODULE_DEVICE_TABLE(ccw, qeth_ids); | 7804 | MODULE_DEVICE_TABLE(ccw, qeth_ids); |
@@ -7725,7 +7936,7 @@ qeth_arp_constructor(struct neighbour *neigh) | |||
7725 | goto out; | 7936 | goto out; |
7726 | 7937 | ||
7727 | rcu_read_lock(); | 7938 | rcu_read_lock(); |
7728 | in_dev = rcu_dereference(__in_dev_get(dev)); | 7939 | in_dev = __in_dev_get_rcu(dev); |
7729 | if (in_dev == NULL) { | 7940 | if (in_dev == NULL) { |
7730 | rcu_read_unlock(); | 7941 | rcu_read_unlock(); |
7731 | return -EINVAL; | 7942 | return -EINVAL; |
@@ -8332,6 +8543,9 @@ again: | |||
8332 | printk("qeth: removed\n"); | 8543 | printk("qeth: removed\n"); |
8333 | } | 8544 | } |
8334 | 8545 | ||
8546 | EXPORT_SYMBOL(qeth_osn_register); | ||
8547 | EXPORT_SYMBOL(qeth_osn_deregister); | ||
8548 | EXPORT_SYMBOL(qeth_osn_assist); | ||
8335 | module_init(qeth_init); | 8549 | module_init(qeth_init); |
8336 | module_exit(qeth_exit); | 8550 | module_exit(qeth_exit); |
8337 | MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); | 8551 | MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); |