Commit 49553319 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: qeth driver.

 - Create symlinks between netdev and groupdev.
 - Remove initialization of device.name.
 - Call qeth_free_card on removal.
 - Remove async hsi.
 - Remove contig memusage.
 - Add check for -EFAULT to copy_from_user/copy_to_user.
 - Inlining some functions to save kernel stack space.
 - vlan header fixes.
 - Replace atomic_return_sub with atomic_add_return.
parent f4a19003
/* /*
* *
* linux/drivers/s390/net/qeth.c ($Revision: 1.126 $) * linux/drivers/s390/net/qeth.c ($Revision: 1.154 $)
* *
* Linux on zSeries OSA Express and HiperSockets support * Linux on zSeries OSA Express and HiperSockets support
* *
...@@ -106,13 +106,12 @@ qeth_eyecatcher(void) ...@@ -106,13 +106,12 @@ qeth_eyecatcher(void)
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/version.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <linux/ctype.h> #include <linux/ctype.h>
...@@ -160,12 +159,12 @@ qeth_eyecatcher(void) ...@@ -160,12 +159,12 @@ qeth_eyecatcher(void)
/****************** MODULE PARAMETER VARIABLES ********************/ /****************** MODULE PARAMETER VARIABLES ********************/
static int qeth_sparebufs = 0; static int qeth_sparebufs = 0;
MODULE_PARM(qeth_sparebufs, "i"); module_param(qeth_sparebufs, int, 0);
MODULE_PARM_DESC(qeth_sparebufs, "the number of pre-allocated spare buffers " MODULE_PARM_DESC(qeth_sparebufs, "the number of pre-allocated spare buffers "
"reserved for low memory situations"); "reserved for low memory situations");
/****************** MODULE STUFF **********************************/ /****************** MODULE STUFF **********************************/
#define VERSION_QETH_C "$Revision: 1.126 $" #define VERSION_QETH_C "$Revision: 1.154 $"
static const char *version = "qeth S/390 OSA-Express driver (" static const char *version = "qeth S/390 OSA-Express driver ("
VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H
QETH_VERSION_IPV6 QETH_VERSION_VLAN ")"; QETH_VERSION_IPV6 QETH_VERSION_VLAN ")";
...@@ -218,9 +217,9 @@ struct tempinfo{ ...@@ -218,9 +217,9 @@ struct tempinfo{
/* thought I could get along without forward declarations... /* thought I could get along without forward declarations...
* just lazyness here */ * just lazyness here */
static int qeth_reinit_thread(void *); static int qeth_reinit_thread(void *);
static void qeth_schedule_recovery(struct qeth_card *card); static inline void qeth_schedule_recovery(struct qeth_card *card);
inline static int static inline int
QETH_IP_VERSION(struct sk_buff *skb) QETH_IP_VERSION(struct sk_buff *skb)
{ {
switch (skb->protocol) { switch (skb->protocol) {
...@@ -648,10 +647,6 @@ qeth_get_prioqueue(struct qeth_card *card, struct sk_buff *skb, ...@@ -648,10 +647,6 @@ qeth_get_prioqueue(struct qeth_card *card, struct sk_buff *skb,
case 1: case 1:
return 0; return 0;
case 4: case 4:
if ((card->can_do_async_iqd) &&
(card->options.async_iqd == ASYNC_IQD)) {
return card->no_queues - 1;
}
if (card->is_multicast_different) { if (card->is_multicast_different) {
if (multicast) { if (multicast) {
return card->is_multicast_different & return card->is_multicast_different &
...@@ -706,11 +701,7 @@ qeth_wakeup(struct qeth_card *card) ...@@ -706,11 +701,7 @@ qeth_wakeup(struct qeth_card *card)
QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
atomic_set(&card->data_has_arrived, 1); atomic_set(&card->data_has_arrived, 1);
spin_lock(&card->wait_q_lock);
if (atomic_read(&card->wait_q_active)) {
wake_up(&card->wait_q); wake_up(&card->wait_q);
}
spin_unlock(&card->wait_q_lock);
} }
static int static int
...@@ -1273,9 +1264,6 @@ qeth_get_next_skb(struct qeth_card *card, ...@@ -1273,9 +1264,6 @@ qeth_get_next_skb(struct qeth_card *card,
goto nomem; goto nomem;
} }
if (card->easy_copy_cap)
memcpy(skb_put(skb, length), data_ptr, length);
QETH_DBF_HEX6(0, trace, &data_ptr, sizeof (void *)); QETH_DBF_HEX6(0, trace, &data_ptr, sizeof (void *));
QETH_DBF_HEX6(0, trace, &skb, sizeof (void *)); QETH_DBF_HEX6(0, trace, &skb, sizeof (void *));
...@@ -1302,7 +1290,6 @@ qeth_get_next_skb(struct qeth_card *card, ...@@ -1302,7 +1290,6 @@ qeth_get_next_skb(struct qeth_card *card,
dev_kfree_skb_irq(skb); dev_kfree_skb_irq(skb);
return NULL; return NULL;
} }
if (!card->easy_copy_cap)
memcpy(skb_put(skb, step), data_ptr, step); memcpy(skb_put(skb, step), data_ptr, step);
len_togo -= step; len_togo -= step;
if (len_togo) { if (len_togo) {
...@@ -1603,11 +1590,14 @@ __qeth_fill_header_add_vlan(struct qeth_hdr *hdr, struct sk_buff *skb, ...@@ -1603,11 +1590,14 @@ __qeth_fill_header_add_vlan(struct qeth_hdr *hdr, struct sk_buff *skb,
#ifdef QETH_VLAN #ifdef QETH_VLAN
struct qeth_card *card; struct qeth_card *card;
/* before we're going to overwrite this location with next hop ip */ /*
* before we're going to overwrite this location with next hop ip.
* v6 uses passthrough, v4 sets the tag in the QDIO header.
*/
card = (struct qeth_card *) skb->dev->priv; card = (struct qeth_card *) skb->dev->priv;
if ((card->vlangrp != NULL) && if ((card->vlangrp != NULL) && vlan_tx_tag_present(skb)) {
vlan_tx_tag_present(skb) && (version == 4)) { hdr->ext_flags = (version == 4) ? QETH_EXT_HEADER_VLAN_FRAME :
hdr->ext_flags = QETH_EXT_HEADER_VLAN_FRAME; QETH_EXT_HEADER_INCLUDE_VLAN_TAG;
hdr->vlan_id = vlan_tx_tag_get(skb); hdr->vlan_id = vlan_tx_tag_get(skb);
} }
#endif #endif
...@@ -1684,7 +1674,9 @@ qeth_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb, ...@@ -1684,7 +1674,9 @@ qeth_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb,
skb->dev->broadcast, 6)) { /* broadcast? */ skb->dev->broadcast, 6)) { /* broadcast? */
hdr->flags = QETH_CAST_BROADCAST | QETH_HEADER_PASSTHRU; hdr->flags = QETH_CAST_BROADCAST | QETH_HEADER_PASSTHRU;
} else { } else {
hdr->flags = QETH_CAST_UNICAST | QETH_HEADER_PASSTHRU; hdr->flags = (multicast == RTN_MULTICAST) ?
QETH_CAST_MULTICAST | QETH_HEADER_PASSTHRU :
QETH_CAST_UNICAST | QETH_HEADER_PASSTHRU;
} }
} }
sprintf(dbf_text, "filhdr%2x", version); sprintf(dbf_text, "filhdr%2x", version);
...@@ -2356,14 +2348,6 @@ qeth_free_all_spare_bufs(void) ...@@ -2356,14 +2348,6 @@ qeth_free_all_spare_bufs(void)
} }
} }
static __inline__ int
atomic_return_sub(int i, atomic_t * v)
{
int old_val, new_val;
__CS_LOOP(old_val, new_val, v, i, "sr");
return old_val;
}
static inline void static inline void
__qeth_dump_packet_info(struct qeth_card *card, int version, int multicast, __qeth_dump_packet_info(struct qeth_card *card, int version, int multicast,
int queue) int queue)
...@@ -2580,50 +2564,21 @@ qeth_start_softsetup_thread(struct qeth_card *card) ...@@ -2580,50 +2564,21 @@ qeth_start_softsetup_thread(struct qeth_card *card)
static int static int
qeth_sleepon(struct qeth_card *card, int timeout) qeth_sleepon(struct qeth_card *card, int timeout)
{ {
unsigned long flags;
unsigned long start;
int retval;
char dbf_text[15]; char dbf_text[15];
DECLARE_WAITQUEUE(current_wait_q, current);
QETH_DBF_TEXT5(0, trace, "slpn"); QETH_DBF_TEXT5(0, trace, "slpn");
QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
sprintf(dbf_text, "%08x", timeout); sprintf(dbf_text, "%08x", timeout);
QETH_DBF_TEXT5(0, trace, dbf_text); QETH_DBF_TEXT5(0, trace, dbf_text);
add_wait_queue(&card->wait_q, &current_wait_q); wait_event_interruptible_timeout(card->wait_q,
atomic_set(&card->wait_q_active, 1); atomic_read(&card->data_has_arrived),
start = qeth_get_millis(); timeout * HZ);
for (;;) {
set_task_state(current, TASK_INTERRUPTIBLE);
if (atomic_read(&card->data_has_arrived)) { if (atomic_read(&card->data_has_arrived)) {
atomic_set(&card->data_has_arrived, 0); atomic_set(&card->data_has_arrived, 0);
retval = 0; return 0;
goto out;
}
if (qeth_get_millis() - start > timeout) {
retval = -ETIME;
goto out;
}
schedule_timeout(((start + timeout -
qeth_get_millis()) >> 10) * HZ);
}
out:
spin_lock_irqsave(&card->wait_q_lock, flags);
atomic_set(&card->wait_q_active, 0);
spin_unlock_irqrestore(&card->wait_q_lock, flags);
/* we've got to check once again to close the window */
if (atomic_read(&card->data_has_arrived)) {
atomic_set(&card->data_has_arrived, 0);
retval = 0;
} }
return -ETIME;
set_task_state(current, TASK_RUNNING);
remove_wait_queue(&card->wait_q, &current_wait_q);
return retval;
} }
static void static void
...@@ -2634,60 +2589,28 @@ qeth_wakeup_ioctl(struct qeth_card *card) ...@@ -2634,60 +2589,28 @@ qeth_wakeup_ioctl(struct qeth_card *card)
QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
atomic_set(&card->ioctl_data_has_arrived, 1); atomic_set(&card->ioctl_data_has_arrived, 1);
spin_lock(&card->ioctl_wait_q_lock);
if (atomic_read(&card->ioctl_wait_q_active)) {
wake_up(&card->ioctl_wait_q); wake_up(&card->ioctl_wait_q);
}
spin_unlock(&card->ioctl_wait_q_lock);
} }
static int static int
qeth_sleepon_ioctl(struct qeth_card *card, int timeout) qeth_sleepon_ioctl(struct qeth_card *card, int timeout)
{ {
unsigned long flags;
unsigned long start;
int retval;
char dbf_text[15]; char dbf_text[15];
DECLARE_WAITQUEUE(current_wait_q, current);
QETH_DBF_TEXT5(0, trace, "ioctlslpn"); QETH_DBF_TEXT5(0, trace, "ioctlslpn");
QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id);
sprintf(dbf_text, "%08x", timeout); sprintf(dbf_text, "%08x", timeout);
QETH_DBF_TEXT5(0, trace, dbf_text); QETH_DBF_TEXT5(0, trace, dbf_text);
add_wait_queue(&card->ioctl_wait_q, &current_wait_q); wait_event_interruptible_timeout(card->ioctl_wait_q,
atomic_set(&card->ioctl_wait_q_active, 1); atomic_read(&card->
start = qeth_get_millis(); ioctl_data_has_arrived),
for (;;) { timeout * HZ);
set_task_state(current, TASK_INTERRUPTIBLE);
if (atomic_read(&card->ioctl_data_has_arrived)) {
atomic_set(&card->ioctl_data_has_arrived, 0);
retval = 0;
goto out;
}
if (qeth_get_millis() - start > timeout) {
retval = -ETIME;
goto out;
}
schedule_timeout(((start + timeout -
qeth_get_millis()) >> 10) * HZ);
}
out:
spin_lock_irqsave(&card->ioctl_wait_q_lock, flags);
atomic_set(&card->ioctl_wait_q_active, 0);
spin_unlock_irqrestore(&card->ioctl_wait_q_lock, flags);
/* we've got to check once again to close the window */
if (atomic_read(&card->ioctl_data_has_arrived)) { if (atomic_read(&card->ioctl_data_has_arrived)) {
atomic_set(&card->ioctl_data_has_arrived, 0); atomic_set(&card->ioctl_data_has_arrived, 0);
retval = 0; return 0;
} }
return -ETIME;
set_task_state(current, TASK_RUNNING);
remove_wait_queue(&card->ioctl_wait_q, &current_wait_q);
return retval;
} }
/*SNMP IOCTL on Procfile */ /*SNMP IOCTL on Procfile */
...@@ -3227,8 +3150,9 @@ qeth_queryarp(struct qeth_card *card, struct ifreq *req, int version, ...@@ -3227,8 +3150,9 @@ qeth_queryarp(struct qeth_card *card, struct ifreq *req, int version,
result = IPA_REPLY_SUCCESS; result = IPA_REPLY_SUCCESS;
memcpy(((char *) (card->ioctl_data_buffer)) + sizeof (__u16), memcpy(((char *) (card->ioctl_data_buffer)) + sizeof (__u16),
&(card->number_of_entries), sizeof (int)); &(card->number_of_entries), sizeof (int));
copy_to_user(req->ifr_ifru.ifru_data, if (copy_to_user(req->ifr_ifru.ifru_data,
card->ioctl_data_buffer, data_size); card->ioctl_data_buffer, data_size))
result = -EFAULT;
} }
card->ioctl_buffer_pointer = NULL; card->ioctl_buffer_pointer = NULL;
vfree(card->ioctl_data_buffer); vfree(card->ioctl_data_buffer);
...@@ -3296,13 +3220,17 @@ qeth_send_snmp_control(struct qeth_card *card, struct ifreq *req, ...@@ -3296,13 +3220,17 @@ qeth_send_snmp_control(struct qeth_card *card, struct ifreq *req,
goto snmp_out; goto snmp_out;
} }
if (result == ARP_RETURNCODE_ERROR) { if (result == ARP_RETURNCODE_ERROR) {
copy_to_user(req->ifr_ifru.ifru_data + SNMP_REQUEST_DATA_OFFSET,
card->ioctl_data_buffer, card->ioctl_buffersize);
result = IPA_REPLY_FAILED; result = IPA_REPLY_FAILED;
if (copy_to_user(req->ifr_ifru.ifru_data +
SNMP_REQUEST_DATA_OFFSET, card->ioctl_data_buffer,
card->ioctl_buffersize))
result = -EFAULT;
} else { } else {
copy_to_user(req->ifr_ifru.ifru_data + SNMP_REQUEST_DATA_OFFSET,
card->ioctl_data_buffer, card->ioctl_buffersize);
result = IPA_REPLY_SUCCESS; result = IPA_REPLY_SUCCESS;
if (copy_to_user(req->ifr_ifru.ifru_data +
SNMP_REQUEST_DATA_OFFSET, card->ioctl_data_buffer,
card->ioctl_buffersize))
result = -EFAULT;
} }
snmp_out: snmp_out:
card->number_of_entries = 0; card->number_of_entries = 0;
...@@ -4387,6 +4315,7 @@ qeth_clone_ifa6(struct inet6_ifaddr *src, struct inet6_ifaddr *dest) ...@@ -4387,6 +4315,7 @@ qeth_clone_ifa6(struct inet6_ifaddr *src, struct inet6_ifaddr *dest)
#define QETH_STANDARD_RETVALS \ #define QETH_STANDARD_RETVALS \
ret_val=-EIO; \ ret_val=-EIO; \
if (result == -EFAULT) ret_val = -EFAULT; \
if (result==IPA_REPLY_SUCCESS) ret_val=0; \ if (result==IPA_REPLY_SUCCESS) ret_val=0; \
if (result==IPA_REPLY_FAILED) ret_val=-EIO; \ if (result==IPA_REPLY_FAILED) ret_val=-EIO; \
if (result==IPA_REPLY_OPNOTSUPP) ret_val=-EOPNOTSUPP if (result==IPA_REPLY_OPNOTSUPP) ret_val=-EOPNOTSUPP
...@@ -4413,7 +4342,8 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -4413,7 +4342,8 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if ((cmd < SIOCDEVPRIVATE) || (cmd > SIOCDEVPRIVATE + 5)) if ((cmd < SIOCDEVPRIVATE) || (cmd > SIOCDEVPRIVATE + 5))
return -EOPNOTSUPP; return -EOPNOTSUPP;
copy_from_user(buff, rq->ifr_ifru.ifru_data, sizeof (buff)); if (copy_from_user(buff, rq->ifr_ifru.ifru_data, sizeof (buff)))
return -EFAULT;
data = buff; data = buff;
if ((!atomic_read(&card->is_registered)) || if ((!atomic_read(&card->is_registered)) ||
...@@ -5957,7 +5887,7 @@ qeth_recover(void *data) ...@@ -5957,7 +5887,7 @@ qeth_recover(void *data)
} }
} }
static void static inline void
qeth_schedule_recovery(struct qeth_card *card) qeth_schedule_recovery(struct qeth_card *card)
{ {
if (card) { if (card) {
...@@ -6172,8 +6102,9 @@ qeth_qdio_output_handler(struct ccw_device *cdev, ...@@ -6172,8 +6102,9 @@ qeth_qdio_output_handler(struct ccw_device *cdev,
} }
} }
buffers_used = atomic_return_sub(count, buffers_used = atomic_add_return(-count,
&card->outbound_used_buffers[queue]); &card->outbound_used_buffers[queue])
+ count;
switch (card->send_state[queue]) { switch (card->send_state[queue]) {
case SEND_STATE_PACK: case SEND_STATE_PACK:
...@@ -6205,7 +6136,7 @@ __qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb) ...@@ -6205,7 +6136,7 @@ __qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb)
PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id); PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id);
break; break;
default: default:
PRINT_WARN("unknown error %d on device %s\n", PTR_ERR(irb), PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb),
cdev->dev.bus_id); cdev->dev.bus_id);
} }
return PTR_ERR(irb); return PTR_ERR(irb);
...@@ -6504,7 +6435,7 @@ qeth_interrupt_handler_qdio(struct ccw_device *cdev, unsigned long intparm, ...@@ -6504,7 +6435,7 @@ qeth_interrupt_handler_qdio(struct ccw_device *cdev, unsigned long intparm,
QETH_DBF_HEX0(0, sense, irb, QETH_DBF_SENSE_LEN); QETH_DBF_HEX0(0, sense, irb, QETH_DBF_SENSE_LEN);
} }
if ((rqparam == READ_CONF_DATA_STATE) || (rqparam == NOP_STATE)) { if (rqparam == NOP_STATE) {
qeth_wakeup(card); qeth_wakeup(card);
return; return;
} }
...@@ -6645,18 +6576,17 @@ qeth_clear_card(struct qeth_card *card, int qdio_clean, int use_halt) ...@@ -6645,18 +6576,17 @@ qeth_clear_card(struct qeth_card *card, int qdio_clean, int use_halt)
} }
static void static void
qeth_free_card(struct qeth_card *card) qeth_free_card_stuff(struct qeth_card *card)
{ {
int i, j; int i, j;
int element_count;
struct qeth_vipa_entry *e, *e2; struct qeth_vipa_entry *e, *e2;
if (!card) if (!card)
return; return;
QETH_DBF_TEXT3(0, trace, "free"); QETH_DBF_TEXT3(0, trace, "freest");
QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
QETH_DBF_TEXT1(0, setup, "free"); QETH_DBF_TEXT1(0, setup, "freest");
QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id); QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id);
write_lock(&card->vipa_list_lock); write_lock(&card->vipa_list_lock);
...@@ -6668,10 +6598,8 @@ qeth_free_card(struct qeth_card *card) ...@@ -6668,10 +6598,8 @@ qeth_free_card(struct qeth_card *card)
} }
write_unlock(&card->vipa_list_lock); write_unlock(&card->vipa_list_lock);
element_count = (card->options.memusage == MEMUSAGE_DISCONTIG) ?
BUFFER_MAX_ELEMENTS : 1;
for (i = 0; i < card->options.inbound_buffer_count; i++) { for (i = 0; i < card->options.inbound_buffer_count; i++) {
for (j = 0; j < element_count; j++) { for (j = 0; j < BUFFER_MAX_ELEMENTS; j++) {
if (card->inbound_buffer_pool_entry[i][j]) { if (card->inbound_buffer_pool_entry[i][j]) {
kfree(card->inbound_buffer_pool_entry[i][j]); kfree(card->inbound_buffer_pool_entry[i][j]);
card->inbound_buffer_pool_entry[i][j] = NULL; card->inbound_buffer_pool_entry[i][j] = NULL;
...@@ -6687,7 +6615,22 @@ qeth_free_card(struct qeth_card *card) ...@@ -6687,7 +6615,22 @@ qeth_free_card(struct qeth_card *card)
if (card->dma_stuff) if (card->dma_stuff)
kfree(card->dma_stuff); kfree(card->dma_stuff);
if (card->dev) if (card->dev)
kfree(card->dev); free_netdev(card->dev);
}
static void
qeth_free_card(struct qeth_card *card)
{
if (!card)
return;
QETH_DBF_TEXT3(0, trace, "free");
QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
QETH_DBF_TEXT1(0, setup, "free");
QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id);
vfree(card); /* we checked against NULL already */ vfree(card); /* we checked against NULL already */
} }
...@@ -6816,6 +6759,10 @@ qeth_remove_card(struct qeth_card *card, int method) ...@@ -6816,6 +6759,10 @@ qeth_remove_card(struct qeth_card *card, int method)
hard_start_xmit */ hard_start_xmit */
if (atomic_read(&card->is_registered)) { if (atomic_read(&card->is_registered)) {
/* Remove sysfs symlinks. */
sysfs_remove_link(&card->gdev->dev.kobj, card->dev_name);
sysfs_remove_link(&card->dev->class_dev.kobj,
card->gdev->dev.bus_id);
QETH_DBF_TEXT2(0, trace, "unregdev"); QETH_DBF_TEXT2(0, trace, "unregdev");
qeth_unregister_netdev(card); qeth_unregister_netdev(card);
qeth_wait_nonbusy(QETH_REMOVE_WAIT_TIME); qeth_wait_nonbusy(QETH_REMOVE_WAIT_TIME);
...@@ -6903,6 +6850,8 @@ qeth_peer_func_level(int level) ...@@ -6903,6 +6850,8 @@ qeth_peer_func_level(int level)
} }
/* returns last four digits of bus_id */ /* returns last four digits of bus_id */
/* FIXME: device driver shouldn't be aware of bus_id format - but don't know
what else to use... (CH) */
static inline __u16 static inline __u16
__raw_devno_from_bus_id(char *id) __raw_devno_from_bus_id(char *id)
{ {
...@@ -7029,6 +6978,12 @@ qeth_idx_activate_read(struct qeth_card *card) ...@@ -7029,6 +6978,12 @@ qeth_idx_activate_read(struct qeth_card *card)
((!QETH_IDX_NO_PORTNAME_REQUIRED(card->dma_stuff->recbuf)) && ((!QETH_IDX_NO_PORTNAME_REQUIRED(card->dma_stuff->recbuf)) &&
(card->type == QETH_CARD_TYPE_OSAE));; (card->type == QETH_CARD_TYPE_OSAE));;
/*
* however, as the portname indication of OSA is wrong, we have to
* do this:
*/
card->portname_required = (card->type == QETH_CARD_TYPE_OSAE);
memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf), 2); memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf), 2);
if (temp != qeth_peer_func_level(card->func_level)) { if (temp != qeth_peer_func_level(card->func_level)) {
QETH_DBF_TEXT1(0, trace, "IRFL"); QETH_DBF_TEXT1(0, trace, "IRFL");
...@@ -7076,14 +7031,14 @@ qeth_idx_activate_write(struct qeth_card *card) ...@@ -7076,14 +7031,14 @@ qeth_idx_activate_write(struct qeth_card *card)
memcpy(QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->sendbuf), memcpy(QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->sendbuf),
&card->func_level, 2); &card->func_level, 2);
temp = _ccw_device_get_device_number(card->ddev); temp = __raw_devno_from_bus_id(card->ddev->dev.bus_id);
memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(card->dma_stuff->sendbuf), &temp, 2); memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(card->dma_stuff->sendbuf), &temp, 2);
temp = (card->cula << 8) + card->unit_addr2; temp = (card->cula << 8) + card->unit_addr2;
memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(card->dma_stuff->sendbuf), memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(card->dma_stuff->sendbuf),
&temp, 2); &temp, 2);
QETH_DBF_TEXT2(0, trace, "iaww"); QETH_DBF_TEXT2(0, trace, "iaww");
QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT2(0, trace, card->wdev->dev.bus_id);
QETH_DBF_HEX2(0, control, card->dma_stuff->sendbuf, QETH_DBF_HEX2(0, control, card->dma_stuff->sendbuf,
QETH_DBF_CONTROL_LEN); QETH_DBF_CONTROL_LEN);
...@@ -7112,7 +7067,7 @@ qeth_idx_activate_write(struct qeth_card *card) ...@@ -7112,7 +7067,7 @@ qeth_idx_activate_write(struct qeth_card *card)
if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) { if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) {
QETH_DBF_TEXT1(0, trace, "IWWT"); QETH_DBF_TEXT1(0, trace, "IWWT");
QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT1(0, trace, card->wdev->dev.bus_id);
PRINT_ERR("IDX_ACTIVATE(wr) on write channel device %s: " PRINT_ERR("IDX_ACTIVATE(wr) on write channel device %s: "
"timeout\n", card->wdev->dev.bus_id); "timeout\n", card->wdev->dev.bus_id);
return -EIO; return -EIO;
...@@ -7153,19 +7108,19 @@ qeth_idx_activate_write(struct qeth_card *card) ...@@ -7153,19 +7108,19 @@ qeth_idx_activate_write(struct qeth_card *card)
if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) { if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) {
QETH_DBF_TEXT1(0, trace, "IWRT"); QETH_DBF_TEXT1(0, trace, "IWRT");
QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT1(0, trace, card->wdev->dev.bus_id);
PRINT_ERR("IDX_ACTIVATE(rd) on write channel device %s: " PRINT_ERR("IDX_ACTIVATE(rd) on write channel device %s: "
"timeout\n", card->wdev->dev.bus_id); "timeout\n", card->wdev->dev.bus_id);
return -EIO; return -EIO;
} }
QETH_DBF_TEXT2(0, trace, "iawr"); QETH_DBF_TEXT2(0, trace, "iawr");
QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT2(0, trace, card->wdev->dev.bus_id);
QETH_DBF_HEX2(0, control, card->dma_stuff->recbuf, QETH_DBF_HEX2(0, control, card->dma_stuff->recbuf,
QETH_DBF_CONTROL_LEN); QETH_DBF_CONTROL_LEN);
if (!(QETH_IS_IDX_ACT_POS_REPLY(card->dma_stuff->recbuf))) { if (!(QETH_IS_IDX_ACT_POS_REPLY(card->dma_stuff->recbuf))) {
QETH_DBF_TEXT1(0, trace, "IWNR"); QETH_DBF_TEXT1(0, trace, "IWNR");
QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT1(0, trace, card->wdev->dev.bus_id);
PRINT_ERR("IDX_ACTIVATE on write channel device %s: negative " PRINT_ERR("IDX_ACTIVATE on write channel device %s: negative "
"reply\n", card->wdev->dev.bus_id); "reply\n", card->wdev->dev.bus_id);
return -EIO; return -EIO;
...@@ -7174,7 +7129,7 @@ qeth_idx_activate_write(struct qeth_card *card) ...@@ -7174,7 +7129,7 @@ qeth_idx_activate_write(struct qeth_card *card)
memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf), 2); memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf), 2);
if ((temp & ~0x0100) != qeth_peer_func_level(card->func_level)) { if ((temp & ~0x0100) != qeth_peer_func_level(card->func_level)) {
QETH_DBF_TEXT1(0, trace, "IWFM"); QETH_DBF_TEXT1(0, trace, "IWFM");
QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT1(0, trace, card->wdev->dev.bus_id);
sprintf(dbf_text, "%4x%4x", card->func_level, temp); sprintf(dbf_text, "%4x%4x", card->func_level, temp);
QETH_DBF_TEXT1(0, trace, dbf_text); QETH_DBF_TEXT1(0, trace, dbf_text);
PRINT_WARN("IDX_ACTIVATE on write channel device %s: function " PRINT_WARN("IDX_ACTIVATE on write channel device %s: function "
...@@ -7345,7 +7300,7 @@ qeth_ulp_setup(struct qeth_card *card) ...@@ -7345,7 +7300,7 @@ qeth_ulp_setup(struct qeth_card *card)
memcpy(QETH_ULP_SETUP_FILTER_TOKEN(card->send_buf), memcpy(QETH_ULP_SETUP_FILTER_TOKEN(card->send_buf),
&card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH); &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
temp = _ccw_device_get_device_number(card->ddev); temp = __raw_devno_from_bus_id(card->ddev->dev.bus_id);
memcpy(QETH_ULP_SETUP_CUA(card->send_buf), &temp, 2); memcpy(QETH_ULP_SETUP_CUA(card->send_buf), &temp, 2);
temp = (card->cula << 8) + card->unit_addr2; temp = (card->cula << 8) + card->unit_addr2;
memcpy(QETH_ULP_SETUP_REAL_DEVADDR(card->send_buf), &temp, 2); memcpy(QETH_ULP_SETUP_REAL_DEVADDR(card->send_buf), &temp, 2);
...@@ -8224,11 +8179,6 @@ qeth_hardsetup_card(struct qeth_card *card, int in_recovery) ...@@ -8224,11 +8179,6 @@ qeth_hardsetup_card(struct qeth_card *card, int in_recovery)
card->dev->init = qeth_init_dev; card->dev->init = qeth_init_dev;
if (card->options.memusage == MEMUSAGE_CONTIG) {
card->easy_copy_cap =
qeth_determine_easy_copy_cap(card->type);
} else
card->easy_copy_cap = 0;
card->ipa_timeout = qeth_get_ipa_timeout(card->type); card->ipa_timeout = qeth_get_ipa_timeout(card->type);
} }
...@@ -8492,30 +8442,21 @@ qeth_fill_qeth_card_options(struct qeth_card *card) ...@@ -8492,30 +8442,21 @@ qeth_fill_qeth_card_options(struct qeth_card *card)
card->options.default_queue = QETH_DEFAULT_QUEUE; card->options.default_queue = QETH_DEFAULT_QUEUE;
card->options.inbound_buffer_count = DEFAULT_BUFFER_COUNT; card->options.inbound_buffer_count = DEFAULT_BUFFER_COUNT;
card->options.polltime = QETH_MAX_INPUT_THRESHOLD; card->options.polltime = QETH_MAX_INPUT_THRESHOLD;
card->options.memusage = MEMUSAGE_DISCONTIG;
card->options.macaddr_mode = MACADDR_NONCANONICAL; card->options.macaddr_mode = MACADDR_NONCANONICAL;
card->options.broadcast_mode = BROADCAST_ALLRINGS; card->options.broadcast_mode = BROADCAST_ALLRINGS;
card->options.fake_broadcast = DONT_FAKE_BROADCAST; card->options.fake_broadcast = DONT_FAKE_BROADCAST;
card->options.ena_ipat = ENABLE_TAKEOVER; card->options.ena_ipat = ENABLE_TAKEOVER;
card->options.add_hhlen = DEFAULT_ADD_HHLEN; card->options.add_hhlen = DEFAULT_ADD_HHLEN;
card->options.fake_ll = DONT_FAKE_LL; card->options.fake_ll = DONT_FAKE_LL;
card->options.async_iqd = SYNC_IQD;
} }
static struct qeth_card * static int
qeth_alloc_card(void) qeth_alloc_card_stuff(struct qeth_card *card)
{ {
struct qeth_card *card;
QETH_DBF_TEXT3(0, trace, "alloccrd");
card = (struct qeth_card *) vmalloc(sizeof (struct qeth_card));
if (!card) if (!card)
goto exit_card; return -EINVAL;
memset(card, 0, sizeof (struct qeth_card));
init_waitqueue_head(&card->wait_q);
init_waitqueue_head(&card->ioctl_wait_q);
qeth_fill_qeth_card_options(card); QETH_DBF_TEXT3(0, trace, "alccrdst");
card->dma_stuff = card->dma_stuff =
(struct qeth_dma_stuff *) kmalloc(sizeof (struct qeth_dma_stuff), (struct qeth_dma_stuff *) kmalloc(sizeof (struct qeth_dma_stuff),
...@@ -8549,7 +8490,42 @@ qeth_alloc_card(void) ...@@ -8549,7 +8490,42 @@ qeth_alloc_card(void)
goto exit_stats; goto exit_stats;
memset(card->stats, 0, sizeof (struct net_device_stats)); memset(card->stats, 0, sizeof (struct net_device_stats));
spin_lock_init(&card->wait_q_lock); /* setup net_device stuff */
card->dev->priv = card;
/* setup net_device_stats stuff */
/* =nothing yet */
return 0;
/* these are quick exits in case of failures of the kmallocs */
exit_stats:
free_netdev(card->dev);
exit_dev:
kfree(card->dma_stuff->sendbuf);
exit_dma2:
kfree(card->dma_stuff->recbuf);
exit_dma1:
kfree(card->dma_stuff);
exit_dma:
return -ENOMEM;
}
static struct qeth_card *
qeth_alloc_card(void)
{
struct qeth_card *card;
QETH_DBF_TEXT3(0, trace, "alloccrd");
card = (struct qeth_card *) vmalloc(sizeof (struct qeth_card));
if (!card)
return NULL;
memset(card, 0, sizeof (struct qeth_card));
init_waitqueue_head(&card->wait_q);
init_waitqueue_head(&card->ioctl_wait_q);
qeth_fill_qeth_card_options(card);
spin_lock_init(&card->softsetup_lock); spin_lock_init(&card->softsetup_lock);
spin_lock_init(&card->hardsetup_lock); spin_lock_init(&card->hardsetup_lock);
spin_lock_init(&card->ioctl_lock); spin_lock_init(&card->ioctl_lock);
...@@ -8576,30 +8552,9 @@ qeth_alloc_card(void) ...@@ -8576,30 +8552,9 @@ qeth_alloc_card(void)
card->csum_enable_mask = IPA_CHECKSUM_DEFAULT_ENABLE_MASK; card->csum_enable_mask = IPA_CHECKSUM_DEFAULT_ENABLE_MASK;
/* setup net_device stuff */
card->dev->priv = card;
strncpy(card->dev->name, card->dev_name, IFNAMSIZ);
/* setup net_device_stats stuff */
/* =nothing yet */
/* and return to the sender */ /* and return to the sender */
return card; return card;
/* these are quick exits in case of failures of the kmallocs */
exit_stats:
kfree(card->dev);
exit_dev:
kfree(card->dma_stuff->sendbuf);
exit_dma2:
kfree(card->dma_stuff->recbuf);
exit_dma1:
kfree(card->dma_stuff);
exit_dma:
kfree(card);
exit_card:
return NULL;
} }
static int static int
...@@ -8634,53 +8589,32 @@ static int ...@@ -8634,53 +8589,32 @@ static int
qeth_init_ringbuffers2(struct qeth_card *card) qeth_init_ringbuffers2(struct qeth_card *card)
{ {
int i, j; int i, j;
int failed = 0;
int discont_mem, element_count;
long alloc_size;
QETH_DBF_TEXT3(0, trace, "irb2"); QETH_DBF_TEXT3(0, trace, "irb2");
QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id);
discont_mem = (card->options.memusage == MEMUSAGE_DISCONTIG);
element_count = (discont_mem) ? BUFFER_MAX_ELEMENTS : 1;
alloc_size = (discont_mem) ? PAGE_SIZE : BUFFER_SIZE;
if (discont_mem) {
for (i = 0; i < card->options.inbound_buffer_count; i++) { for (i = 0; i < card->options.inbound_buffer_count; i++) {
for (j = 0; j < element_count; j++) { for (j = 0; j < BUFFER_MAX_ELEMENTS; j++) {
card->inbound_buffer_pool_entry[i][j] = card->inbound_buffer_pool_entry[i][j] =
kmalloc(alloc_size, GFP_KERNEL); kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!card->inbound_buffer_pool_entry[i][j]) { if (!card->inbound_buffer_pool_entry[i][j]) {
failed = 1;
goto out; goto out;
} }
} }
card->inbound_buffer_pool_entry_used[i] = BUFFER_UNUSED; card->inbound_buffer_pool_entry_used[i] = BUFFER_UNUSED;
} }
} else {
for (i = 0; i < card->options.inbound_buffer_count; i++) {
card->inbound_buffer_pool_entry[i][0] =
kmalloc(alloc_size, GFP_KERNEL);
if (!card->inbound_buffer_pool_entry[i][0])
failed = 1;
for (j = 1; j < element_count; j++)
card->inbound_buffer_pool_entry[i][j] =
card->inbound_buffer_pool_entry[i][0] +
PAGE_SIZE * j;
card->inbound_buffer_pool_entry_used[i] = BUFFER_UNUSED;
}
}
spin_lock_init(&card->requeue_input_lock);
return 0;
out: out:
if (failed) {
for (i = 0; i < card->options.inbound_buffer_count; i++) { for (i = 0; i < card->options.inbound_buffer_count; i++) {
for (j = 0; j < QDIO_MAX_ELEMENTS_PER_BUFFER; j++) { for (j = 0; j < QDIO_MAX_ELEMENTS_PER_BUFFER; j++) {
if (card->inbound_buffer_pool_entry[i][j]) { if (card->inbound_buffer_pool_entry[i][j]) {
if (j < element_count) if (j < BUFFER_MAX_ELEMENTS)
kfree(card-> kfree(card->
inbound_buffer_pool_entry inbound_buffer_pool_entry[i][j]);
[i][j]); card->inbound_buffer_pool_entry[i][j] = NULL;
card->inbound_buffer_pool_entry
[i][j] = NULL;
} }
} }
} }
...@@ -8689,11 +8623,7 @@ qeth_init_ringbuffers2(struct qeth_card *card) ...@@ -8689,11 +8623,7 @@ qeth_init_ringbuffers2(struct qeth_card *card)
card->outbound_ringbuffer[i] = NULL; card->outbound_ringbuffer[i] = NULL;
} }
return -ENOMEM; return -ENOMEM;
}
spin_lock_init(&card->requeue_input_lock);
return 0;
} }
/* also locked from outside (setup_lock) */ /* also locked from outside (setup_lock) */
...@@ -8843,32 +8773,23 @@ qeth_correct_routing_status(struct qeth_card *card) ...@@ -8843,32 +8773,23 @@ qeth_correct_routing_status(struct qeth_card *card)
__qeth_correct_routing_status_v6(card); __qeth_correct_routing_status_v6(card);
} }
static struct net_device * static int
qeth_init_netdev(struct net_device *dev) qeth_init_netdev(struct qeth_card *card)
{ {
struct qeth_card *card = NULL;
int result; int result;
char dbf_text[15]; char dbf_text[15];
if (!dev) {
PRINT_ERR("qeth_init_netdev called with no device!\n");
goto out;
}
card = (struct qeth_card *) dev->priv;
strcpy(card->dev_name, dev->name);
result = qeth_register_netdev(card); result = qeth_register_netdev(card);
if (result) { if (result) {
PRINT_ALL(" register_netdev %s -- rc=%i\n", PRINT_ALL(" register_netdev %s -- rc=%i\n",
((struct qeth_card *) firstcard->dev->priv)-> card->dev_name, result);
dev_name, result);
sprintf(dbf_text, "rgnd%4x", (__u16) result); sprintf(dbf_text, "rgnd%4x", (__u16) result);
QETH_DBF_TEXT2(1, trace, dbf_text); QETH_DBF_TEXT2(1, trace, dbf_text);
atomic_set(&card->is_registered, 0); atomic_set(&card->is_registered, 0);
goto out; goto out;
} }
strcpy(card->dev_name, dev->name); strcpy(card->dev_name, card->dev->name);
atomic_set(&card->write_busy, 0); atomic_set(&card->write_busy, 0);
atomic_set(&card->is_registered, 1); atomic_set(&card->is_registered, 1);
...@@ -8885,7 +8806,7 @@ qeth_init_netdev(struct net_device *dev) ...@@ -8885,7 +8806,7 @@ qeth_init_netdev(struct net_device *dev)
schedule_work(&card->tqueue); schedule_work(&card->tqueue);
out: out:
qeth_wakeup_procfile(); qeth_wakeup_procfile();
return dev; return result;
} }
...@@ -9092,11 +9013,11 @@ qeth_procfile_open(struct inode *inode, struct file *file) ...@@ -9092,11 +9013,11 @@ qeth_procfile_open(struct inode *inode, struct file *file)
length += sprintf(buffer + length, length += sprintf(buffer + length,
"devices CHPID " "devices CHPID "
"device cardtype port chksum prio-q'ing " "device cardtype port chksum prio-q'ing "
"rtr fsz C cnt\n"); "rtr fsz cnt\n");
length += sprintf(buffer + length, length += sprintf(buffer + length,
"-------------------- --- ----" "-------------------- --- ----"
"------ -------------- -- -- ---------- " "------ -------------- -- -- ---------- "
"--- --- - ---\n"); "--- --- ---\n");
card = firstcard; card = firstcard;
while (card) { while (card) {
strcpy(checksum_str, strcpy(checksum_str,
...@@ -9212,7 +9133,7 @@ qeth_procfile_open(struct inode *inode, struct file *file) ...@@ -9212,7 +9133,7 @@ qeth_procfile_open(struct inode *inode, struct file *file)
} else { } else {
length += sprintf(buffer + length, length += sprintf(buffer + length,
"%s/%s/%s x%02X %10s %14s %2i" "%s/%s/%s x%02X %10s %14s %2i"
" %2s %10s %3s %3s %c %3i\n", " %2s %10s %3s %3s %3i\n",
card->rdev->dev.bus_id, card->rdev->dev.bus_id,
card->wdev->dev.bus_id, card->wdev->dev.bus_id,
card->ddev->dev.bus_id, card->ddev->dev.bus_id,
...@@ -9222,8 +9143,6 @@ qeth_procfile_open(struct inode *inode, struct file *file) ...@@ -9222,8 +9143,6 @@ qeth_procfile_open(struct inode *inode, struct file *file)
card->is_guest_lan), card->is_guest_lan),
card->options.portno, checksum_str, card->options.portno, checksum_str,
queueing_str, router_str, bufsize_str, queueing_str, router_str, bufsize_str,
(card->options.memusage ==
MEMUSAGE_CONTIG) ? 'c' : ' ',
card->options.inbound_buffer_count); card->options.inbound_buffer_count);
} }
card = card->next; card = card->next;
...@@ -9662,7 +9581,8 @@ qeth_procfile_getinterfaces(unsigned long arg) ...@@ -9662,7 +9581,8 @@ qeth_procfile_getinterfaces(unsigned long arg)
qeth_version = 0; qeth_version = 0;
number_of_devices = 0; number_of_devices = 0;
copy_from_user((void *) parms, (void *) arg, sizeof (parms)); if (copy_from_user((void *) parms, (void *) arg, sizeof (parms)))
return -EFAULT;
memcpy(&data_size, parms, sizeof (__u32)); memcpy(&data_size, parms, sizeof (__u32));
if (!(data_size > 0)) if (!(data_size > 0))
...@@ -9725,7 +9645,8 @@ qeth_procfile_getinterfaces(unsigned long arg) ...@@ -9725,7 +9645,8 @@ qeth_procfile_getinterfaces(unsigned long arg)
sizeof (__u32)); sizeof (__u32));
memcpy(((char *) buffer_pointer) + (3 * sizeof (__u32)), memcpy(((char *) buffer_pointer) + (3 * sizeof (__u32)),
&number_of_devices, sizeof (__u32)); &number_of_devices, sizeof (__u32));
copy_to_user((char *) arg, buffer, data_len); if (copy_to_user((char *) arg, buffer, data_len))
result = -EFAULT;
vfree(buffer); vfree(buffer);
out: out:
read_unlock(&list_lock); read_unlock(&list_lock);
...@@ -10017,7 +9938,6 @@ static struct ccw_driver qeth_ccw_driver = { ...@@ -10017,7 +9938,6 @@ static struct ccw_driver qeth_ccw_driver = {
}; };
static struct device qeth_root_dev = { static struct device qeth_root_dev = {
.name = "QETH Devices",
.bus_id = "qeth", .bus_id = "qeth",
}; };
...@@ -10466,44 +10386,6 @@ qeth_portno_store(struct device *dev, const char *buf, size_t count) ...@@ -10466,44 +10386,6 @@ qeth_portno_store(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(portno, 0644, qeth_portno_show, qeth_portno_store); static DEVICE_ATTR(portno, 0644, qeth_portno_show, qeth_portno_store);
static ssize_t
qeth_contig_show(struct device *dev, char *buf)
{
struct qeth_card *card = dev->driver_data;
if (!card)
return -EINVAL;
return sprintf(buf, "%s\n",
(card->options.memusage == MEMUSAGE_CONTIG)?"yes":"no");
}
static ssize_t
qeth_contig_store(struct device *dev, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
int i;
char *tmp;
if (!card)
return count;
if (atomic_read(&card->is_hardsetup))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
if (i == 0)
card->options.memusage = MEMUSAGE_DISCONTIG;
else if (i == 1)
card->options.memusage = MEMUSAGE_CONTIG;
else
return -EINVAL;
return count;
}
static DEVICE_ATTR(contig, 0644, qeth_contig_show, qeth_contig_store);
static ssize_t static ssize_t
qeth_polltime_show(struct device *dev, char *buf) qeth_polltime_show(struct device *dev, char *buf)
{ {
...@@ -10585,7 +10467,7 @@ qeth_takeover_show(struct device *dev, char *buf) ...@@ -10585,7 +10467,7 @@ qeth_takeover_show(struct device *dev, char *buf)
return -EINVAL; return -EINVAL;
return sprintf(buf, "%s\n", return sprintf(buf, "%s\n",
(card->options.ena_ipat == ENABLE_TAKEOVER)?"yes":"no"); (card->options.ena_ipat == ENABLE_TAKEOVER)?"1":"0");
} }
static ssize_t static ssize_t
...@@ -10602,9 +10484,9 @@ qeth_takeover_store(struct device *dev, const char *buf, size_t count) ...@@ -10602,9 +10484,9 @@ qeth_takeover_store(struct device *dev, const char *buf, size_t count)
return -EPERM; return -EPERM;
i = simple_strtoul(buf, &tmp, 16); i = simple_strtoul(buf, &tmp, 16);
if (i == 0) if (i == 1)
card->options.ena_ipat = ENABLE_TAKEOVER; card->options.ena_ipat = ENABLE_TAKEOVER;
else if (i == 1) else if (i == 0)
card->options.ena_ipat = DISABLE_TAKEOVER; card->options.ena_ipat = DISABLE_TAKEOVER;
else else
return -EINVAL; return -EINVAL;
...@@ -10623,7 +10505,7 @@ qeth_macaddr_show(struct device *dev, char *buf) ...@@ -10623,7 +10505,7 @@ qeth_macaddr_show(struct device *dev, char *buf)
return -EINVAL; return -EINVAL;
return sprintf(buf, "%s\n", return sprintf(buf, "%s\n",
(card->options.macaddr_mode == MACADDR_CANONICAL)?"yes":"no"); (card->options.macaddr_mode == MACADDR_CANONICAL)?"1":"0");
} }
static ssize_t static ssize_t
...@@ -10661,7 +10543,7 @@ qeth_fakebr_show(struct device *dev, char *buf) ...@@ -10661,7 +10543,7 @@ qeth_fakebr_show(struct device *dev, char *buf)
return -EINVAL; return -EINVAL;
return sprintf(buf, "%s\n", return sprintf(buf, "%s\n",
(card->options.fake_broadcast == FAKE_BROADCAST)?"yes":"no"); (card->options.fake_broadcast == FAKE_BROADCAST)?"1":"0");
} }
static ssize_t static ssize_t
...@@ -10699,7 +10581,7 @@ qeth_fakell_show(struct device *dev, char *buf) ...@@ -10699,7 +10581,7 @@ qeth_fakell_show(struct device *dev, char *buf)
return -EINVAL; return -EINVAL;
return sprintf(buf, "%s\n", return sprintf(buf, "%s\n",
(card->options.fake_ll == FAKE_LL)?"yes":"no"); (card->options.fake_ll == FAKE_LL)?"1":"0");
} }
static ssize_t static ssize_t
...@@ -10728,44 +10610,6 @@ qeth_fakell_store(struct device *dev, const char *buf, size_t count) ...@@ -10728,44 +10610,6 @@ qeth_fakell_store(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(fake_ll, 0644, qeth_fakell_show, qeth_fakell_store); static DEVICE_ATTR(fake_ll, 0644, qeth_fakell_show, qeth_fakell_store);
static ssize_t
qeth_hsi_show(struct device *dev, char *buf)
{
struct qeth_card *card = dev->driver_data;
if (!card)
return -EINVAL;
return sprintf(buf, "%s\n",
(card->options.async_iqd == ASYNC_IQD)?"async":"sync");
}
static ssize_t
qeth_hsi_store(struct device *dev, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
int i;
char *tmp;
if (!card)
return count;
if (atomic_read(&card->is_hardsetup))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
if (i == 0)
card->options.async_iqd = SYNC_IQD;
else if (i == 1)
card->options.async_iqd = ASYNC_IQD;
else
return -EINVAL;
return count;
}
static DEVICE_ATTR(async_hsi, 0644, qeth_hsi_show, qeth_hsi_store);
static ssize_t static ssize_t
qeth_broadcast_show(struct device *dev, char *buf) qeth_broadcast_show(struct device *dev, char *buf)
{ {
...@@ -10900,6 +10744,7 @@ qeth_probe_device(struct ccwgroup_device *gdev) ...@@ -10900,6 +10744,7 @@ qeth_probe_device(struct ccwgroup_device *gdev)
} }
gdev->dev.driver_data = card; gdev->dev.driver_data = card;
card->gdev = gdev;
card->rdev = gdev->cdev[0]; card->rdev = gdev->cdev[0];
gdev->cdev[0]->handler = qeth_interrupt_handler_read; gdev->cdev[0]->handler = qeth_interrupt_handler_read;
...@@ -10917,7 +10762,6 @@ qeth_probe_device(struct ccwgroup_device *gdev) ...@@ -10917,7 +10762,6 @@ qeth_probe_device(struct ccwgroup_device *gdev)
if (ret != 0) if (ret != 0)
goto out; goto out;
snprintf(gdev->dev.name, DEVICE_NAME_SIZE, "qeth device");
return 0; return 0;
out: out:
put_device(&gdev->dev); put_device(&gdev->dev);
...@@ -10980,8 +10824,20 @@ qeth_activate(struct qeth_card *card) ...@@ -10980,8 +10824,20 @@ qeth_activate(struct qeth_card *card)
/* this was previously done in chandev_initnetdevice */ /* this was previously done in chandev_initnetdevice */
snprintf(card->dev->name, 8, "%s%%d", snprintf(card->dev->name, 8, "%s%%d",
qeth_get_dev_basename(card->type, card->link_type)); qeth_get_dev_basename(card->type, card->link_type));
qeth_init_netdev(card->dev); if (qeth_init_netdev(card))
goto out_remove;
if (sysfs_create_link(&card->gdev->dev.kobj, &card->dev->class_dev.kobj,
card->dev_name)) {
qeth_unregister_netdev(card);
goto out_remove;
}
if (sysfs_create_link(&card->dev->class_dev.kobj, &card->gdev->dev.kobj,
card->gdev->dev.bus_id)) {
sysfs_remove_link(&card->gdev->dev.kobj, card->dev_name);
qeth_unregister_netdev(card);
goto out_remove;
}
return 0; /* success */ return 0; /* success */
out_remove: out_remove:
...@@ -11006,7 +10862,7 @@ qeth_remove_device(struct ccwgroup_device *gdev) ...@@ -11006,7 +10862,7 @@ qeth_remove_device(struct ccwgroup_device *gdev)
__qeth_remove_attributes(&gdev->dev); __qeth_remove_attributes(&gdev->dev);
gdev->dev.driver_data = NULL; gdev->dev.driver_data = NULL;
if (card) if (card)
kfree(card); qeth_free_card(card);
put_device(&gdev->dev); put_device(&gdev->dev);
return 0; return 0;
} }
...@@ -11014,17 +10870,15 @@ qeth_remove_device(struct ccwgroup_device *gdev) ...@@ -11014,17 +10870,15 @@ qeth_remove_device(struct ccwgroup_device *gdev)
static int static int
qeth_set_online(struct ccwgroup_device *gdev) qeth_set_online(struct ccwgroup_device *gdev)
{ {
int rc;
struct qeth_card *card = gdev->dev.driver_data; struct qeth_card *card = gdev->dev.driver_data;
int ret;
BUG_ON(!card); BUG_ON(!card);
ret = qeth_activate(card); rc = qeth_alloc_card_stuff(card);
if (ret == 0)
snprintf(gdev->dev.name, DEVICE_NAME_SIZE, "%s", return rc ? rc : qeth_activate(card);
qeth_get_cardname_short(card->type, card->link_type,
card->is_guest_lan));
return ret;
} }
static int static int
...@@ -11040,14 +10894,12 @@ qeth_set_offline(struct ccwgroup_device *gdev) ...@@ -11040,14 +10894,12 @@ qeth_set_offline(struct ccwgroup_device *gdev)
QETH_DBF_TEXT4(0, trace, "freecard"); QETH_DBF_TEXT4(0, trace, "freecard");
memset(card->dev, 0, sizeof (struct net_device));
card->dev->priv = card;
strncpy(card->dev->name, card->dev_name, IFNAMSIZ);
ccw_device_set_offline(card->ddev); ccw_device_set_offline(card->ddev);
ccw_device_set_offline(card->wdev); ccw_device_set_offline(card->wdev);
ccw_device_set_offline(card->rdev); ccw_device_set_offline(card->rdev);
qeth_free_card_stuff(card);
return 0; return 0;
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#define QETH_NAME " qeth" #define QETH_NAME " qeth"
#define VERSION_QETH_H "$Revision: 1.49 $" #define VERSION_QETH_H "$Revision: 1.56 $"
/******************** CONFIG STUFF ***********************/ /******************** CONFIG STUFF ***********************/
//#define QETH_DBF_LIKE_HELL //#define QETH_DBF_LIKE_HELL
...@@ -567,13 +567,6 @@ struct sparebufs { ...@@ -567,13 +567,6 @@ struct sparebufs {
#define QETH_LOCK_NORMAL 1 #define QETH_LOCK_NORMAL 1
#define QETH_LOCK_FLUSH 2 #define QETH_LOCK_FLUSH 2
#define QETH_MAX_DEVICES 16
/* DEPENDENCY ON QETH_MAX_DEVICES.
*__MOUDLE_STRING expects simple literals */
#define QETH_MAX_DEVICES_TIMES_4 64
#define QETH_MAX_DEVNAMES 16
#define QETH_DEVNAME "eth"
#define QETH_TX_TIMEOUT 100*HZ /* 100 seconds */ #define QETH_TX_TIMEOUT 100*HZ /* 100 seconds */
#define QETH_REMOVE_WAIT_TIME 200 #define QETH_REMOVE_WAIT_TIME 200
...@@ -581,8 +574,6 @@ struct sparebufs { ...@@ -581,8 +574,6 @@ struct sparebufs {
#define QETH_IDLE_WAIT_TIME 10 #define QETH_IDLE_WAIT_TIME 10
#define QETH_WAIT_BEFORE_2ND_DOIO 1000 #define QETH_WAIT_BEFORE_2ND_DOIO 1000
#define QETH_MAX_PARM_LEN 128
#define QETH_FAKE_LL_LEN ETH_HLEN /* 14 */ #define QETH_FAKE_LL_LEN ETH_HLEN /* 14 */
#define QETH_FAKE_LL_PROT_LEN 2 #define QETH_FAKE_LL_PROT_LEN 2
#define QETH_FAKE_LL_ADDR_LEN ETH_ALEN /* 6 */ #define QETH_FAKE_LL_ADDR_LEN ETH_ALEN /* 6 */
...@@ -609,16 +600,12 @@ struct sparebufs { ...@@ -609,16 +600,12 @@ struct sparebufs {
IPA_PDU_HEADER_SIZE+sizeof(struct ipa_cmd)), \ IPA_PDU_HEADER_SIZE+sizeof(struct ipa_cmd)), \
QETH_RCD_LENGTH) QETH_RCD_LENGTH)
#define QETH_FINAL_STATUS_TIMEOUT 1500
#define QETH_CLEAR_TIMEOUT 1500
#define QETH_RCD_TIMEOUT 1500
#define QETH_NOP_TIMEOUT 1500 #define QETH_NOP_TIMEOUT 1500
#define QETH_QUIESCE_NETDEV_TIME 300 #define QETH_QUIESCE_NETDEV_TIME 300
#define QETH_QUIESCE_WAIT_BEFORE_CLEAR 4000 #define QETH_QUIESCE_WAIT_BEFORE_CLEAR 4000
#define QETH_QUIESCE_WAIT_AFTER_CLEAR 4000 #define QETH_QUIESCE_WAIT_AFTER_CLEAR 4000
#define NOP_STATE 0x1001 #define NOP_STATE 0x1001
#define READ_CONF_DATA_STATE 0x1002
#define IDX_ACTIVATE_READ_STATE 0x1003 #define IDX_ACTIVATE_READ_STATE 0x1003
#define IDX_ACTIVATE_WRITE_STATE 0x1004 #define IDX_ACTIVATE_WRITE_STATE 0x1004
#define MPC_SETUP_STATE 0x1005 #define MPC_SETUP_STATE 0x1005
...@@ -647,8 +634,6 @@ struct sparebufs { ...@@ -647,8 +634,6 @@ struct sparebufs {
#define BROADCAST_LOCAL 1 #define BROADCAST_LOCAL 1
#define MACADDR_NONCANONICAL 0 #define MACADDR_NONCANONICAL 0
#define MACADDR_CANONICAL 1 #define MACADDR_CANONICAL 1
#define MEMUSAGE_DISCONTIG 0
#define MEMUSAGE_CONTIG 1
#define ENABLE_TAKEOVER 0 #define ENABLE_TAKEOVER 0
#define DISABLE_TAKEOVER 1 #define DISABLE_TAKEOVER 1
#define FAKE_BROADCAST 0 #define FAKE_BROADCAST 0
...@@ -656,8 +641,6 @@ struct sparebufs { ...@@ -656,8 +641,6 @@ struct sparebufs {
#define FAKE_LL 0 #define FAKE_LL 0
#define DONT_FAKE_LL 1 #define DONT_FAKE_LL 1
#define SYNC_IQD 0
#define ASYNC_IQD 1
#define QETH_BREAKOUT_LEAVE 1 #define QETH_BREAKOUT_LEAVE 1
#define QETH_BREAKOUT_AGAIN 2 #define QETH_BREAKOUT_AGAIN 2
...@@ -684,9 +667,6 @@ struct sparebufs { ...@@ -684,9 +667,6 @@ struct sparebufs {
#define SENSE_RESETTING_EVENT_BYTE 1 #define SENSE_RESETTING_EVENT_BYTE 1
#define SENSE_RESETTING_EVENT_FLAG 0x80 #define SENSE_RESETTING_EVENT_FLAG 0x80
#define DEFAULT_RCD_CMD 0x72
#define DEFAULT_RCD_COUNT 0x80
#define BUFFER_USED 1 #define BUFFER_USED 1
#define BUFFER_UNUSED -1 #define BUFFER_UNUSED -1
...@@ -744,14 +724,12 @@ struct qeth_card_options { ...@@ -744,14 +724,12 @@ struct qeth_card_options {
int polltime; int polltime;
char portname[9]; char portname[9];
int portno; int portno;
int memusage;
int broadcast_mode; int broadcast_mode;
int macaddr_mode; int macaddr_mode;
int ena_ipat; int ena_ipat;
int fake_broadcast; int fake_broadcast;
int add_hhlen; int add_hhlen;
int fake_ll; int fake_ll;
int async_iqd;
}; };
struct qeth_hdr { struct qeth_hdr {
...@@ -811,7 +789,6 @@ struct qeth_perf_stats { ...@@ -811,7 +789,6 @@ struct qeth_perf_stats {
/* ugly. I know. */ /* ugly. I know. */
struct qeth_card { /* pointed to by dev->priv */ struct qeth_card { /* pointed to by dev->priv */
int easy_copy_cap;
/* pointer to options (defaults + parameters) */ /* pointer to options (defaults + parameters) */
struct qeth_card_options options; struct qeth_card_options options;
...@@ -930,8 +907,6 @@ struct qeth_card { /* pointed to by dev->priv */ ...@@ -930,8 +907,6 @@ struct qeth_card { /* pointed to by dev->priv */
int is_multicast_different; /* if multicast traffic is to be sent int is_multicast_different; /* if multicast traffic is to be sent
on a different queue, this is the on a different queue, this is the
queue+no_queues */ queue+no_queues */
int can_do_async_iqd; /* 1 only on IQD that provides async
unicast sigas */
__u32 ipa_supported; __u32 ipa_supported;
__u32 ipa_enabled; __u32 ipa_enabled;
__u32 ipa6_supported; __u32 ipa6_supported;
...@@ -950,6 +925,7 @@ struct qeth_card { /* pointed to by dev->priv */ ...@@ -950,6 +925,7 @@ struct qeth_card { /* pointed to by dev->priv */
int unique_id; int unique_id;
/* device and I/O data */ /* device and I/O data */
struct ccwgroup_device *gdev;
struct ccw_device *rdev; struct ccw_device *rdev;
struct ccw_device *wdev; struct ccw_device *wdev;
struct ccw_device *ddev; struct ccw_device *ddev;
...@@ -969,8 +945,6 @@ struct qeth_card { /* pointed to by dev->priv */ ...@@ -969,8 +945,6 @@ struct qeth_card { /* pointed to by dev->priv */
atomic_t ioctl_data_has_arrived; atomic_t ioctl_data_has_arrived;
wait_queue_head_t ioctl_wait_q; wait_queue_head_t ioctl_wait_q;
atomic_t ioctl_wait_q_active;
spinlock_t ioctl_wait_q_lock;
/* stuff under 2 gb */ /* stuff under 2 gb */
struct qeth_dma_stuff *dma_stuff; struct qeth_dma_stuff *dma_stuff;
...@@ -987,8 +961,6 @@ struct qeth_card { /* pointed to by dev->priv */ ...@@ -987,8 +961,6 @@ struct qeth_card { /* pointed to by dev->priv */
atomic_t shutdown_phase; atomic_t shutdown_phase;
atomic_t data_has_arrived; atomic_t data_has_arrived;
wait_queue_head_t wait_q; wait_queue_head_t wait_q;
atomic_t wait_q_active;
spinlock_t wait_q_lock; /* for wait_q_active and wait_q */
atomic_t clear_succeeded0; atomic_t clear_succeeded0;
atomic_t clear_succeeded1; atomic_t clear_succeeded1;
...@@ -1034,21 +1006,6 @@ qeth_get_arphrd_type(int cardtype, int linktype) ...@@ -1034,21 +1006,6 @@ qeth_get_arphrd_type(int cardtype, int linktype)
} }
} }
inline static int
qeth_determine_easy_copy_cap(int cardtype)
{
switch (cardtype) {
case QETH_CARD_TYPE_UNKNOWN:
return 0; /* better be cautious */
case QETH_CARD_TYPE_OSAE:
return 1;
case QETH_CARD_TYPE_IQD:
return 0;
default:
return 0; /* ?? */
}
}
inline static __u8 inline static __u8
qeth_get_adapter_type_for_ipa(int link_type) qeth_get_adapter_type_for_ipa(int link_type)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment