Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52358cb5 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 's390-qeth-next'



Julian Wiedmann says:

====================
s390/qeth: updates 2018-11-08

please apply the following qeth patches to net-next.

The first patch allows one more device type to query the FW for a MAC address,
the others are all basically just removal of duplicated or unused code.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 04087d9a ded9da1f
Loading
Loading
Loading
Loading
+2 −17
Original line number Diff line number Diff line
@@ -314,7 +314,7 @@ struct qeth_hdr_layer3 {
	__u16 frame_offset;
	union {
		/* TX: */
		u8 ipv6_addr[16];
		struct in6_addr ipv6_addr;
		struct ipv4 {
			u8 res[12];
			u32 addr;
@@ -665,7 +665,6 @@ struct qeth_card_blkt {

#define QETH_BROADCAST_WITH_ECHO    0x01
#define QETH_BROADCAST_WITHOUT_ECHO 0x02
#define QETH_LAYER2_MAC_READ	    0x01
#define QETH_LAYER2_MAC_REGISTERED  0x02
struct qeth_card_info {
	unsigned short unit_addr2;
@@ -775,7 +774,6 @@ struct qeth_switch_info {
#define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT

struct qeth_card {
	struct list_head list;
	enum qeth_card_states state;
	spinlock_t lock;
	struct ccwgroup_device *gdev;
@@ -827,11 +825,6 @@ struct qeth_card {
	struct work_struct close_dev_work;
};

struct qeth_card_list_struct {
	struct list_head list;
	rwlock_t rwlock;
};

struct qeth_trap_id {
	__u16 lparnr;
	char vmname[8];
@@ -978,11 +971,11 @@ int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
void qeth_core_free_discipline(struct qeth_card *);

/* exports for qeth discipline device drivers */
extern struct qeth_card_list_struct qeth_core_card_list;
extern struct kmem_cache *qeth_core_header_cache;
extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];

struct net_device *qeth_clone_netdev(struct net_device *orig);
struct qeth_card *qeth_get_card_by_busid(char *bus_id);
void qeth_set_recovery_task(struct qeth_card *);
void qeth_clear_recovery_task(struct qeth_card *);
void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
@@ -1025,9 +1018,6 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
	int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
	void *reply_param);
unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset);
int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, struct sk_buff *skb,
			     struct qeth_hdr *hdr, unsigned int offset,
			     unsigned int hd_len);
int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
			struct sk_buff *skb, struct qeth_hdr *hdr,
			unsigned int offset, unsigned int hd_len,
@@ -1058,11 +1048,6 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
				      struct net_device *dev,
				      netdev_features_t features);
int qeth_vm_request_mac(struct qeth_card *card);
int qeth_add_hw_header(struct qeth_card *card, struct sk_buff *skb,
		       struct qeth_hdr **hdr, unsigned int hdr_len,
		       unsigned int proto_len, unsigned int *elements);
void qeth_fill_tso_ext(struct qeth_hdr_tso *hdr, unsigned int payload_len,
		       struct sk_buff *skb, unsigned int proto_len);
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
	      struct qeth_qdio_out_q *queue, int ipv, int cast_type,
	      void (*fill_header)(struct qeth_card *card, struct qeth_hdr *hdr,
+57 −80
Original line number Diff line number Diff line
@@ -54,8 +54,6 @@ struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS] = {
};
EXPORT_SYMBOL_GPL(qeth_dbf);

struct qeth_card_list_struct qeth_core_card_list;
EXPORT_SYMBOL_GPL(qeth_core_card_list);
struct kmem_cache *qeth_core_header_cache;
EXPORT_SYMBOL_GPL(qeth_core_header_cache);
static struct kmem_cache *qeth_qdio_outbuf_cache;
@@ -2837,6 +2835,17 @@ static void qeth_fill_ipacmd_header(struct qeth_card *card,
	cmd->hdr.prot_version = prot;
}

void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob)
{
	u8 prot_type = qeth_mpc_select_prot_type(card);

	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
	memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data), &prot_type, 1);
	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
}
EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd);

struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
		enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
{
@@ -2844,6 +2853,7 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,

	iob = qeth_get_buffer(&card->write);
	if (iob) {
		qeth_prepare_ipa_cmd(card, iob);
		qeth_fill_ipacmd_header(card, __ipa_cmd(iob), ipacmd, prot);
	} else {
		dev_warn(&card->gdev->dev,
@@ -2856,17 +2866,6 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,
}
EXPORT_SYMBOL_GPL(qeth_get_ipacmd_buffer);

void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob)
{
	u8 prot_type = qeth_mpc_select_prot_type(card);

	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
	memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data), &prot_type, 1);
	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
}
EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd);

/**
 * qeth_send_ipa_cmd() - send an IPA command
 *
@@ -2881,7 +2880,6 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
	int rc;

	QETH_CARD_TEXT(card, 4, "sendipa");
	qeth_prepare_ipa_cmd(card, iob);
	rc = qeth_send_control_data(card, IPA_CMD_LENGTH,
						iob, reply_cb, reply_param);
	if (rc == -ETIME) {
@@ -3777,7 +3775,7 @@ EXPORT_SYMBOL_GPL(qeth_count_elements);
 * The number of needed buffer elements is returned in @elements.
 * Error to create the hdr is indicated by returning with < 0.
 */
int qeth_add_hw_header(struct qeth_card *card, struct sk_buff *skb,
static int qeth_add_hw_header(struct qeth_card *card, struct sk_buff *skb,
			      struct qeth_hdr **hdr, unsigned int hdr_len,
			      unsigned int proto_len, unsigned int *elements)
{
@@ -3849,7 +3847,6 @@ int qeth_add_hw_header(struct qeth_card *card, struct sk_buff *skb,
	skb_copy_from_linear_data(skb, ((char *)*hdr) + hdr_len, proto_len);
	return 0;
}
EXPORT_SYMBOL_GPL(qeth_add_hw_header);

static void __qeth_fill_buffer(struct sk_buff *skb,
			       struct qeth_qdio_out_buffer *buf,
@@ -3972,9 +3969,9 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
	return flush_cnt;
}

int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, struct sk_buff *skb,
			     struct qeth_hdr *hdr, unsigned int offset,
			     unsigned int hd_len)
static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue,
				    struct sk_buff *skb, struct qeth_hdr *hdr,
				    unsigned int offset, unsigned int hd_len)
{
	int index = queue->next_buf_to_fill;
	struct qeth_qdio_out_buffer *buffer = queue->bufs[index];
@@ -3990,7 +3987,6 @@ int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, struct sk_buff *skb,
	qeth_flush_buffers(queue, index, 1);
	return 0;
}
EXPORT_SYMBOL_GPL(qeth_do_send_packet_fast);

int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
			struct sk_buff *skb, struct qeth_hdr *hdr,
@@ -4082,8 +4078,9 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
}
EXPORT_SYMBOL_GPL(qeth_do_send_packet);

void qeth_fill_tso_ext(struct qeth_hdr_tso *hdr, unsigned int payload_len,
		       struct sk_buff *skb, unsigned int proto_len)
static void qeth_fill_tso_ext(struct qeth_hdr_tso *hdr,
			      unsigned int payload_len, struct sk_buff *skb,
			      unsigned int proto_len)
{
	struct qeth_hdr_ext_tso *ext = &hdr->ext;

@@ -4096,7 +4093,6 @@ void qeth_fill_tso_ext(struct qeth_hdr_tso *hdr, unsigned int payload_len,
	ext->mss = skb_shinfo(skb)->gso_size;
	ext->dg_hdr_len = proto_len;
}
EXPORT_SYMBOL_GPL(qeth_fill_tso_ext);

int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
	      struct qeth_qdio_out_q *queue, int ipv, int cast_type,
@@ -4119,7 +4115,7 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
		proto_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
	} else {
		hw_hdr_len = sizeof(struct qeth_hdr);
		proto_len = IS_IQD(card) ? ETH_HLEN : 0;
		proto_len = (IS_IQD(card) && IS_LAYER2(card)) ? ETH_HLEN : 0;
	}

	rc = skb_cow_head(skb, hw_hdr_len);
@@ -4235,16 +4231,18 @@ static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
		struct qeth_reply *reply, unsigned long data)
{
	struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
	struct qeth_ipacmd_setadpparms *adp_cmd;

	QETH_CARD_TEXT(card, 4, "chgmaccb");
	if (qeth_setadpparms_inspect_rc(cmd))
		return 0;

	if (IS_LAYER3(card) || !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
		ether_addr_copy(card->dev->dev_addr,
				cmd->data.setadapterparms.data.change_addr.addr);
		card->info.mac_bits |= QETH_LAYER2_MAC_READ;
	}
	adp_cmd = &cmd->data.setadapterparms;
	if (IS_LAYER2(card) && IS_OSD(card) && !IS_VM_NIC(card) &&
	    !(adp_cmd->hdr.flags & QETH_SETADP_FLAGS_VIRTUAL_MAC))
		return 0;

	ether_addr_copy(card->dev->dev_addr, adp_cmd->data.change_addr.addr);
	return 0;
}

@@ -4499,9 +4497,6 @@ static int qeth_send_ipa_snmp_cmd(struct qeth_card *card,

	QETH_CARD_TEXT(card, 4, "sendsnmp");

	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
	/* adjust PDU length fields in IPA_PDU_HEADER */
	s1 = (u32) IPA_PDU_HEADER_SIZE + len;
	s2 = (u32) len;
@@ -5480,34 +5475,11 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
}
EXPORT_SYMBOL_GPL(qeth_get_setassparms_cmd);

static int qeth_send_setassparms(struct qeth_card *card,
				 struct qeth_cmd_buffer *iob, u16 len,
				 long data, int (*reply_cb)(struct qeth_card *,
							    struct qeth_reply *,
							    unsigned long),
				 void *reply_param)
{
	int rc;
	struct qeth_ipa_cmd *cmd;

	QETH_CARD_TEXT(card, 4, "sendassp");

	cmd = __ipa_cmd(iob);
	if (len <= sizeof(__u32))
		cmd->data.setassparms.data.flags_32bit = (__u32) data;
	else   /* (len > sizeof(__u32)) */
		memcpy(&cmd->data.setassparms.data, (void *) data, len);

	rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);
	return rc;
}

int qeth_send_simple_setassparms_prot(struct qeth_card *card,
				      enum qeth_ipa_funcs ipa_func,
				      u16 cmd_code, long data,
				      enum qeth_prot_versions prot)
{
	int rc;
	int length = 0;
	struct qeth_cmd_buffer *iob;

@@ -5517,9 +5489,9 @@ int qeth_send_simple_setassparms_prot(struct qeth_card *card,
	iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, length, prot);
	if (!iob)
		return -ENOMEM;
	rc = qeth_send_setassparms(card, iob, length, data,
				   qeth_setassparms_cb, NULL);
	return rc;

	__ipa_cmd(iob)->data.setassparms.data.flags_32bit = (__u32) data;
	return qeth_send_ipa_cmd(card, iob, qeth_setassparms_cb, NULL);
}
EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms_prot);

@@ -5806,9 +5778,6 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
		break;
	}

	write_lock_irq(&qeth_core_card_list.rwlock);
	list_add_tail(&card->list, &qeth_core_card_list.list);
	write_unlock_irq(&qeth_core_card_list.rwlock);
	return 0;

err_disc:
@@ -5833,9 +5802,6 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev)
		qeth_core_free_discipline(card);
	}

	write_lock_irq(&qeth_core_card_list.rwlock);
	list_del(&card->list);
	write_unlock_irq(&qeth_core_card_list.rwlock);
	free_netdev(card->dev);
	qeth_core_free_card(card);
	put_device(&gdev->dev);
@@ -5950,6 +5916,21 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
	.restore = qeth_core_restore,
};

struct qeth_card *qeth_get_card_by_busid(char *bus_id)
{
	struct ccwgroup_device *gdev;
	struct qeth_card *card;

	gdev = get_ccwgroupdev_by_busid(&qeth_core_ccwgroup_driver, bus_id);
	if (!gdev)
		return NULL;

	card = dev_get_drvdata(&gdev->dev);
	put_device(&gdev->dev);
	return card;
}
EXPORT_SYMBOL_GPL(qeth_get_card_by_busid);

int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
	struct qeth_card *card = dev->ml_priv;
@@ -6381,16 +6362,16 @@ static int qeth_ipa_checksum_run_cmd(struct qeth_card *card,
				     enum qeth_prot_versions prot)
{
	struct qeth_cmd_buffer *iob;
	int rc = -ENOMEM;

	QETH_CARD_TEXT(card, 4, "chkdocmd");
	iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
				       sizeof(__u32), prot);
	if (iob)
		rc = qeth_send_setassparms(card, iob, sizeof(__u32), data,
					   qeth_ipa_checksum_run_cmd_cb,
	if (!iob)
		return -ENOMEM;

	__ipa_cmd(iob)->data.setassparms.data.flags_32bit = (__u32) data;
	return qeth_send_ipa_cmd(card, iob, qeth_ipa_checksum_run_cmd_cb,
				 chksum_cb);
	return rc;
}

static int qeth_send_checksum_on(struct qeth_card *card, int cstype,
@@ -6488,8 +6469,7 @@ static int qeth_set_tso_on(struct qeth_card *card,
	if (!iob)
		return -ENOMEM;

	rc = qeth_send_setassparms(card, iob, 0, 0 /* unused */,
				   qeth_start_tso_cb, &tso_data);
	rc = qeth_send_ipa_cmd(card, iob, qeth_start_tso_cb, &tso_data);
	if (rc)
		return rc;

@@ -6506,10 +6486,9 @@ static int qeth_set_tso_on(struct qeth_card *card,
	}

	/* enable TSO capability */
	caps.supported = 0;
	caps.enabled = QETH_IPA_LARGE_SEND_TCP;
	rc = qeth_send_setassparms(card, iob, sizeof(caps), (long) &caps,
				   qeth_setassparms_get_caps_cb, &caps);
	__ipa_cmd(iob)->data.setassparms.data.caps.enabled =
		QETH_IPA_LARGE_SEND_TCP;
	rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_get_caps_cb, &caps);
	if (rc) {
		qeth_set_tso_off(card, prot);
		return rc;
@@ -6688,8 +6667,6 @@ static int __init qeth_core_init(void)
	int rc;

	pr_info("loading core functions\n");
	INIT_LIST_HEAD(&qeth_core_card_list.list);
	rwlock_init(&qeth_core_card_list.rwlock);

	qeth_wq = create_singlethread_workqueue("qeth_wq");
	if (!qeth_wq) {
+0 −1
Original line number Diff line number Diff line
@@ -144,7 +144,6 @@ unsigned char IPA_PDU_HEADER[] = {
		sizeof(struct qeth_ipa_cmd) % 256,
	0x00, 0x00, 0x00, 0x40,
};
EXPORT_SYMBOL_GPL(IPA_PDU_HEADER);

struct ipa_rc_msg {
	enum qeth_ipa_return_codes rc;
+18 −14
Original line number Diff line number Diff line
@@ -80,7 +80,9 @@ enum qeth_card_types {
};

#define IS_IQD(card)	((card)->info.type == QETH_CARD_TYPE_IQD)
#define IS_OSD(card)	((card)->info.type == QETH_CARD_TYPE_OSD)
#define IS_OSN(card)	((card)->info.type == QETH_CARD_TYPE_OSN)
#define IS_VM_NIC(card)	((card)->info.guestlan)

#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
/* only the first two bytes are looked at in qeth_get_cardname_short */
@@ -529,17 +531,20 @@ struct qeth_query_switch_attributes {
	__u8  reserved3[8];
};

#define QETH_SETADP_FLAGS_VIRTUAL_MAC	0x80	/* for CHANGE_ADDR_READ_MAC */

struct qeth_ipacmd_setadpparms_hdr {
	__u32 supp_hw_cmds;
	__u32 reserved1;
	__u16 cmdlength;
	__u16 reserved2;
	__u32 command_code;
	__u16 return_code;
	__u8  used_total;
	__u8  seq_no;
	__u32 reserved3;
} __attribute__ ((packed));
	u32 supp_hw_cmds;
	u32 reserved1;
	u16 cmdlength;
	u16 reserved2;
	u32 command_code;
	u16 return_code;
	u8 used_total;
	u8 seq_no;
	u8 flags;
	u8 reserved3[3];
};

struct qeth_ipacmd_setadpparms {
	struct qeth_ipacmd_setadpparms_hdr hdr;
@@ -828,10 +833,9 @@ enum qeth_ipa_arp_return_codes {
extern const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
extern const char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);

#define QETH_SETASS_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
#define QETH_SETASS_BASE_LEN (IPA_PDU_HEADER_SIZE + \
			      sizeof(struct qeth_ipacmd_hdr) + \
			      sizeof(struct qeth_ipacmd_setassparms_hdr))
#define QETH_IPA_ARP_DATA_POS(buffer) (buffer + IPA_PDU_HEADER_SIZE + \
				       QETH_SETASS_BASE_LEN)
#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
			      sizeof(struct qeth_ipacmd_setadpparms_hdr))
#define QETH_SNMP_SETADP_CMDLENGTH 16
+12 −33
Original line number Diff line number Diff line
@@ -36,28 +36,6 @@ static void qeth_l2_vnicc_init(struct qeth_card *card);
static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc,
					  u32 *timeout);

static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no)
{
	struct qeth_card *card;
	struct net_device *ndev;
	__u16 temp_dev_no;
	unsigned long flags;
	struct ccw_dev_id read_devid;

	ndev = NULL;
	memcpy(&temp_dev_no, read_dev_no, 2);
	read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
	list_for_each_entry(card, &qeth_core_card_list.list, list) {
		ccw_device_get_id(CARD_RDEV(card), &read_devid);
		if (read_devid.devno == temp_dev_no) {
			ndev = card->dev;
			break;
		}
	}
	read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
	return ndev;
}

static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
{
	int rc;
@@ -461,12 +439,9 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
		/* fall back to alternative mechanism: */
	}

	if (card->info.type == QETH_CARD_TYPE_IQD ||
	    card->info.type == QETH_CARD_TYPE_OSM ||
	    card->info.type == QETH_CARD_TYPE_OSX ||
	    card->info.guestlan) {
	if (!IS_OSN(card)) {
		rc = qeth_setadpparms_change_macaddr(card);
		if (!rc)
		if (!rc && is_valid_ether_addr(card->dev->dev_addr))
			goto out;
		QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %x: %#x\n",
				 CARD_DEVID(card), rc);
@@ -917,6 +892,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
				       PAGE_SIZE * (QDIO_MAX_ELEMENTS_PER_BUFFER - 1));
	}

	if (!is_valid_ether_addr(card->dev->dev_addr))
		qeth_l2_request_initial_mac(card);
	netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
	rc = register_netdev(card->dev);
@@ -1288,13 +1264,16 @@ int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
		  int (*data_cb)(struct sk_buff *))
{
	struct qeth_card *card;
	char bus_id[16];
	u16 devno;

	*dev = qeth_l2_netdev_by_devno(read_dev_no);
	if (*dev == NULL)
		return -ENODEV;
	card = (*dev)->ml_priv;
	if (!card)
	memcpy(&devno, read_dev_no, 2);
	sprintf(bus_id, "0.0.%04x", devno);
	card = qeth_get_card_by_busid(bus_id);
	if (!card || !IS_OSN(card))
		return -ENODEV;
	*dev = card->dev;

	QETH_CARD_TEXT(card, 2, "osnreg");
	if ((assist_cb == NULL) || (data_cb == NULL))
		return -EINVAL;
Loading