|
@@ -137,7 +137,7 @@ static int qeth_setdel_makerc(struct qeth_card *card, int retcode)
|
|
|
rc = 0;
|
|
|
break;
|
|
|
case IPA_RC_L2_UNSUPPORTED_CMD:
|
|
|
- rc = -ENOSYS;
|
|
|
+ rc = -EOPNOTSUPP;
|
|
|
break;
|
|
|
case IPA_RC_L2_ADDR_TABLE_FULL:
|
|
|
rc = -ENOSPC;
|
|
@@ -683,6 +683,39 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
|
|
|
return rc ? -EINVAL : 0;
|
|
|
}
|
|
|
|
|
|
+static void qeth_promisc_to_bridge(struct qeth_card *card)
|
|
|
+{
|
|
|
+ struct net_device *dev = card->dev;
|
|
|
+ enum qeth_ipa_promisc_modes promisc_mode;
|
|
|
+ int role;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ QETH_CARD_TEXT(card, 3, "pmisc2br");
|
|
|
+
|
|
|
+ if (!card->options.sbp.reflect_promisc)
|
|
|
+ return;
|
|
|
+ promisc_mode = (dev->flags & IFF_PROMISC) ? SET_PROMISC_MODE_ON
|
|
|
+ : SET_PROMISC_MODE_OFF;
|
|
|
+ if (promisc_mode == card->info.promisc_mode)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (promisc_mode == SET_PROMISC_MODE_ON) {
|
|
|
+ if (card->options.sbp.reflect_promisc_primary)
|
|
|
+ role = QETH_SBP_ROLE_PRIMARY;
|
|
|
+ else
|
|
|
+ role = QETH_SBP_ROLE_SECONDARY;
|
|
|
+ } else
|
|
|
+ role = QETH_SBP_ROLE_NONE;
|
|
|
+
|
|
|
+ rc = qeth_bridgeport_setrole(card, role);
|
|
|
+ QETH_DBF_TEXT_(SETUP, 2, "bpm%c%04x",
|
|
|
+ (promisc_mode == SET_PROMISC_MODE_ON) ? '+' : '-', rc);
|
|
|
+ if (!rc) {
|
|
|
+ card->options.sbp.role = role;
|
|
|
+ card->info.promisc_mode = promisc_mode;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void qeth_l2_set_multicast_list(struct net_device *dev)
|
|
|
{
|
|
|
struct qeth_card *card = dev->ml_priv;
|
|
@@ -704,9 +737,10 @@ static void qeth_l2_set_multicast_list(struct net_device *dev)
|
|
|
qeth_l2_add_mc(card, ha->addr, 1);
|
|
|
|
|
|
spin_unlock_bh(&card->mclock);
|
|
|
- if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
|
|
|
- return;
|
|
|
- qeth_setadp_promisc_mode(card);
|
|
|
+ if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
|
|
|
+ qeth_setadp_promisc_mode(card);
|
|
|
+ else
|
|
|
+ qeth_promisc_to_bridge(card);
|
|
|
}
|
|
|
|
|
|
static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
@@ -994,7 +1028,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|
|
qeth_bridgeport_query_support(card);
|
|
|
if (card->options.sbp.supported_funcs)
|
|
|
dev_info(&card->gdev->dev,
|
|
|
- "The device represents a HiperSockets Bridge Capable Port\n");
|
|
|
+ "The device represents a Bridge Capable Port\n");
|
|
|
qeth_trace_features(card);
|
|
|
|
|
|
if (!card->dev && qeth_l2_setup_netdev(card)) {
|
|
@@ -1247,7 +1281,8 @@ static int qeth_l2_control_event(struct qeth_card *card,
|
|
|
struct qeth_ipa_cmd *cmd)
|
|
|
{
|
|
|
switch (cmd->hdr.command) {
|
|
|
- case IPA_CMD_SETBRIDGEPORT:
|
|
|
+ case IPA_CMD_SETBRIDGEPORT_OSA:
|
|
|
+ case IPA_CMD_SETBRIDGEPORT_IQD:
|
|
|
if (cmd->data.sbp.hdr.command_code ==
|
|
|
IPA_SBP_BRIDGE_PORT_STATE_CHANGE) {
|
|
|
qeth_bridge_state_change(card, cmd);
|
|
@@ -1533,7 +1568,7 @@ static void qeth_bridge_host_event_worker(struct work_struct *work)
|
|
|
|
|
|
if (data->hostevs.lost_event_mask) {
|
|
|
dev_info(&data->card->gdev->dev,
|
|
|
-"Address notification from the HiperSockets Bridge Port stopped %s (%s)\n",
|
|
|
+"Address notification from the Bridge Port stopped %s (%s)\n",
|
|
|
data->card->dev->name,
|
|
|
(data->hostevs.lost_event_mask == 0x01)
|
|
|
? "Overflow"
|
|
@@ -1617,70 +1652,80 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
|
|
|
struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd)
|
|
|
{
|
|
|
int rc;
|
|
|
+ int is_iqd = (card->info.type == QETH_CARD_TYPE_IQD);
|
|
|
|
|
|
- switch (cbctl->ipa_rc) {
|
|
|
- case IPA_RC_SUCCESS:
|
|
|
+ if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) ||
|
|
|
+ (!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc)))
|
|
|
switch (cbctl->cmd_rc) {
|
|
|
case 0x0000:
|
|
|
rc = 0;
|
|
|
break;
|
|
|
+ case 0x2B04:
|
|
|
case 0x0004:
|
|
|
- rc = -ENOSYS;
|
|
|
+ rc = -EOPNOTSUPP;
|
|
|
break;
|
|
|
+ case 0x2B0C:
|
|
|
case 0x000C: /* Not configured as bridge Port */
|
|
|
rc = -ENODEV; /* maybe not the best code here? */
|
|
|
dev_err(&card->gdev->dev,
|
|
|
- "The HiperSockets device is not configured as a Bridge Port\n");
|
|
|
+ "The device is not configured as a Bridge Port\n");
|
|
|
break;
|
|
|
+ case 0x2B14:
|
|
|
case 0x0014: /* Another device is Primary */
|
|
|
switch (setcmd) {
|
|
|
case IPA_SBP_SET_PRIMARY_BRIDGE_PORT:
|
|
|
rc = -EEXIST;
|
|
|
dev_err(&card->gdev->dev,
|
|
|
- "The HiperSockets LAN already has a primary Bridge Port\n");
|
|
|
+ "The LAN already has a primary Bridge Port\n");
|
|
|
break;
|
|
|
case IPA_SBP_SET_SECONDARY_BRIDGE_PORT:
|
|
|
rc = -EBUSY;
|
|
|
dev_err(&card->gdev->dev,
|
|
|
- "The HiperSockets device is already a primary Bridge Port\n");
|
|
|
+ "The device is already a primary Bridge Port\n");
|
|
|
break;
|
|
|
default:
|
|
|
rc = -EIO;
|
|
|
}
|
|
|
break;
|
|
|
+ case 0x2B18:
|
|
|
case 0x0018: /* This device is currently Secondary */
|
|
|
rc = -EBUSY;
|
|
|
dev_err(&card->gdev->dev,
|
|
|
- "The HiperSockets device is already a secondary Bridge Port\n");
|
|
|
+ "The device is already a secondary Bridge Port\n");
|
|
|
break;
|
|
|
+ case 0x2B1C:
|
|
|
case 0x001C: /* Limit for Secondary devices reached */
|
|
|
rc = -EEXIST;
|
|
|
dev_err(&card->gdev->dev,
|
|
|
- "The HiperSockets LAN cannot have more secondary Bridge Ports\n");
|
|
|
+ "The LAN cannot have more secondary Bridge Ports\n");
|
|
|
break;
|
|
|
+ case 0x2B24:
|
|
|
case 0x0024: /* This device is currently Primary */
|
|
|
rc = -EBUSY;
|
|
|
dev_err(&card->gdev->dev,
|
|
|
- "The HiperSockets device is already a primary Bridge Port\n");
|
|
|
+ "The device is already a primary Bridge Port\n");
|
|
|
break;
|
|
|
+ case 0x2B20:
|
|
|
case 0x0020: /* Not authorized by zManager */
|
|
|
rc = -EACCES;
|
|
|
dev_err(&card->gdev->dev,
|
|
|
- "The HiperSockets device is not authorized to be a Bridge Port\n");
|
|
|
+ "The device is not authorized to be a Bridge Port\n");
|
|
|
break;
|
|
|
default:
|
|
|
rc = -EIO;
|
|
|
}
|
|
|
- break;
|
|
|
- case IPA_RC_NOTSUPP:
|
|
|
- rc = -ENOSYS;
|
|
|
- break;
|
|
|
- case IPA_RC_UNSUPPORTED_COMMAND:
|
|
|
- rc = -ENOSYS;
|
|
|
- break;
|
|
|
- default:
|
|
|
- rc = -EIO;
|
|
|
- }
|
|
|
+ else
|
|
|
+ switch (cbctl->ipa_rc) {
|
|
|
+ case IPA_RC_NOTSUPP:
|
|
|
+ rc = -EOPNOTSUPP;
|
|
|
+ break;
|
|
|
+ case IPA_RC_UNSUPPORTED_COMMAND:
|
|
|
+ rc = -EOPNOTSUPP;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ rc = -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
if (rc) {
|
|
|
QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc);
|
|
|
QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc);
|
|
@@ -1688,6 +1733,13 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+static inline int ipa_cmd_sbp(struct qeth_card *card)
|
|
|
+{
|
|
|
+ return (card->info.type == QETH_CARD_TYPE_IQD) ?
|
|
|
+ IPA_CMD_SETBRIDGEPORT_IQD :
|
|
|
+ IPA_CMD_SETBRIDGEPORT_OSA;
|
|
|
+}
|
|
|
+
|
|
|
static int qeth_bridgeport_query_support_cb(struct qeth_card *card,
|
|
|
struct qeth_reply *reply, unsigned long data)
|
|
|
{
|
|
@@ -1719,7 +1771,7 @@ static void qeth_bridgeport_query_support(struct qeth_card *card)
|
|
|
struct _qeth_sbp_cbctl cbctl;
|
|
|
|
|
|
QETH_CARD_TEXT(card, 2, "brqsuppo");
|
|
|
- iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
|
|
|
+ iob = qeth_get_ipacmd_buffer(card, ipa_cmd_sbp(card), 0);
|
|
|
if (!iob)
|
|
|
return;
|
|
|
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
|
|
@@ -1796,7 +1848,7 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
|
|
|
QETH_CARD_TEXT(card, 2, "brqports");
|
|
|
if (!(card->options.sbp.supported_funcs & IPA_SBP_QUERY_BRIDGE_PORTS))
|
|
|
return -EOPNOTSUPP;
|
|
|
- iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
|
|
|
+ iob = qeth_get_ipacmd_buffer(card, ipa_cmd_sbp(card), 0);
|
|
|
if (!iob)
|
|
|
return -ENOMEM;
|
|
|
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
|
|
@@ -1808,10 +1860,9 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
|
|
|
cmd->data.sbp.hdr.seq_no = 1;
|
|
|
rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
|
|
|
(void *)&cbctl);
|
|
|
- if (rc)
|
|
|
+ if (rc < 0)
|
|
|
return rc;
|
|
|
- rc = qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
|
|
|
- return rc;
|
|
|
+ return qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(qeth_bridgeport_query_ports);
|
|
|
|
|
@@ -1864,7 +1915,7 @@ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
|
|
|
}
|
|
|
if (!(card->options.sbp.supported_funcs & setcmd))
|
|
|
return -EOPNOTSUPP;
|
|
|
- iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
|
|
|
+ iob = qeth_get_ipacmd_buffer(card, ipa_cmd_sbp(card), 0);
|
|
|
if (!iob)
|
|
|
return -ENOMEM;
|
|
|
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
|
|
@@ -1874,10 +1925,9 @@ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
|
|
|
cmd->data.sbp.hdr.seq_no = 1;
|
|
|
rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb,
|
|
|
(void *)&cbctl);
|
|
|
- if (rc)
|
|
|
+ if (rc < 0)
|
|
|
return rc;
|
|
|
- rc = qeth_bridgeport_makerc(card, &cbctl, setcmd);
|
|
|
- return rc;
|
|
|
+ return qeth_bridgeport_makerc(card, &cbctl, setcmd);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1898,7 +1948,7 @@ static int qeth_anset_makerc(struct qeth_card *card, int pnso_rc, u16 response)
|
|
|
case 0x0004:
|
|
|
case 0x0100:
|
|
|
case 0x0106:
|
|
|
- rc = -ENOSYS;
|
|
|
+ rc = -EOPNOTSUPP;
|
|
|
dev_err(&card->gdev->dev,
|
|
|
"Setting address notification failed\n");
|
|
|
break;
|