From 91ced682f9de17ebab5fcb2a70b48e372eb43281 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 10 Oct 2009 09:35:05 +0000 Subject: qlge: Add handler for DCBX firmware event. The driver has nothing to do, but this marker prevents the event from showing up 'not handled'. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_mpi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/qlge/qlge_mpi.c') diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 99e58e3f8e2..2e83c4b8ced 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -446,6 +446,9 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) ql_aen_lost(qdev, mbcp); break; + case AEN_DCBX_CHG: + /* Need to support AEN 8110 */ + break; default: QPRINTK(qdev, DRV, ERR, "Unsupported AE %.08x.\n", mbcp->mbox_out[0]); -- cgit v1.2.3-70-g09d2 From 88051b4e4f270966b9e2ec070822513c46083fe1 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 10 Oct 2009 09:35:06 +0000 Subject: qlge: Store firmware revision as early as possible. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_mpi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/qlge/qlge_mpi.c') diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 2e83c4b8ced..9c0dfe01739 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -317,6 +317,7 @@ static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp) } else { QPRINTK(qdev, DRV, ERR, "Firmware Revision = 0x%.08x.\n", mbcp->mbox_out[1]); + qdev->fw_rev_id = mbcp->mbox_out[1]; status = ql_cam_route_initialize(qdev); if (status) QPRINTK(qdev, IFUP, ERR, -- cgit v1.2.3-70-g09d2 From fda9b77c10a4db06e1431e6494a69e93a9dc5491 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 10 Oct 2009 09:35:08 +0000 Subject: qlge: Get rid of firmware handler debug code. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_mpi.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers/net/qlge/qlge_mpi.c') diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 9c0dfe01739..e497eac5eb4 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -1,25 +1,5 @@ #include "qlge.h" -static void ql_display_mb_sts(struct ql_adapter *qdev, - struct mbox_params *mbcp) -{ - int i; - static char *err_sts[] = { - "Command Complete", - "Command Not Supported", - "Host Interface Error", - "Checksum Error", - "Unused Completion Status", - "Test Failed", - "Command Parameter Error"}; - - QPRINTK(qdev, DRV, DEBUG, "%s.\n", - err_sts[mbcp->mbox_out[0] & 0x0000000f]); - for (i = 0; i < mbcp->out_count; i++) - QPRINTK(qdev, DRV, DEBUG, "mbox_out[%d] = 0x%.08x.\n", - i, mbcp->mbox_out[i]); -} - int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data) { int status; @@ -540,7 +520,6 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) MB_CMD_STS_GOOD) && ((mbcp->mbox_out[0] & 0x0000f000) != MB_CMD_STS_INTRMDT)) { - ql_display_mb_sts(qdev, mbcp); status = -EIO; } end: -- cgit v1.2.3-70-g09d2 From 1d30df24ec85477368e6e38fe1b4d1b67b3be9d4 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 21 Oct 2009 11:07:38 +0000 Subject: qlge: Add ethtool get/set pause parameter. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 2 ++ drivers/net/qlge/qlge_ethtool.c | 33 +++++++++++++++++++++++++++++++++ drivers/net/qlge/qlge_mpi.c | 4 ++-- 3 files changed, 37 insertions(+), 2 deletions(-) (limited to 'drivers/net/qlge/qlge_mpi.c') diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index bc7a2e43c62..6118f50b00a 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -1645,6 +1645,8 @@ int ql_mb_about_fw(struct ql_adapter *qdev); void ql_link_on(struct ql_adapter *qdev); void ql_link_off(struct ql_adapter *qdev); int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control); +int ql_mb_get_port_cfg(struct ql_adapter *qdev); +int ql_mb_set_port_cfg(struct ql_adapter *qdev); int ql_wait_fifo_empty(struct ql_adapter *qdev); #if 1 diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index aac6c6f19a2..dfb5c800cea 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -424,6 +424,37 @@ static int ql_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *c) return ql_update_ring_coalescing(qdev); } +static void ql_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct ql_adapter *qdev = netdev_priv(netdev); + + ql_mb_get_port_cfg(qdev); + if (qdev->link_config & CFG_PAUSE_STD) { + pause->rx_pause = 1; + pause->tx_pause = 1; + } +} + +static int ql_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct ql_adapter *qdev = netdev_priv(netdev); + int status = 0; + + if ((pause->rx_pause) && (pause->tx_pause)) + qdev->link_config |= CFG_PAUSE_STD; + else if (!pause->rx_pause && !pause->tx_pause) + qdev->link_config &= ~CFG_PAUSE_STD; + else + return -EINVAL; + + status = ql_mb_set_port_cfg(qdev); + if (status) + return status; + return status; +} + static u32 ql_get_rx_csum(struct net_device *netdev) { struct ql_adapter *qdev = netdev_priv(netdev); @@ -468,6 +499,8 @@ const struct ethtool_ops qlge_ethtool_ops = { .get_msglevel = ql_get_msglevel, .set_msglevel = ql_set_msglevel, .get_link = ethtool_op_get_link, + .get_pauseparam = ql_get_pauseparam, + .set_pauseparam = ql_set_pauseparam, .get_rx_csum = ql_get_rx_csum, .set_rx_csum = ql_set_rx_csum, .get_tx_csum = ethtool_op_get_tx_csum, diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index e497eac5eb4..81a8489fe21 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -637,7 +637,7 @@ int ql_mb_idc_ack(struct ql_adapter *qdev) * for the current port. * Most likely will block. */ -static int ql_mb_set_port_cfg(struct ql_adapter *qdev) +int ql_mb_set_port_cfg(struct ql_adapter *qdev) { struct mbox_params mbc; struct mbox_params *mbcp = &mbc; @@ -672,7 +672,7 @@ static int ql_mb_set_port_cfg(struct ql_adapter *qdev) * for the current port. * Most likely will block. */ -static int ql_mb_get_port_cfg(struct ql_adapter *qdev) +int ql_mb_get_port_cfg(struct ql_adapter *qdev) { struct mbox_params mbc; struct mbox_params *mbcp = &mbc; -- cgit v1.2.3-70-g09d2 From d8eb59dc8b9e77bb4fa5420ff80142759ad5cd7b Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 21 Oct 2009 11:07:39 +0000 Subject: qlge: Add ethtool blink function. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 6 +++++ drivers/net/qlge/qlge_ethtool.c | 28 +++++++++++++++++++++ drivers/net/qlge/qlge_mpi.c | 55 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) (limited to 'drivers/net/qlge/qlge_mpi.c') diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 6118f50b00a..a5bb3a53653 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -805,6 +805,9 @@ enum { MB_CMD_SET_PORT_CFG = 0x00000122, MB_CMD_GET_PORT_CFG = 0x00000123, MB_CMD_GET_LINK_STS = 0x00000124, + MB_CMD_SET_LED_CFG = 0x00000125, /* Set LED Configuration Register */ + QL_LED_BLINK = 0x03e803e8, + MB_CMD_GET_LED_CFG = 0x00000126, /* Get LED Configuration Register */ MB_CMD_SET_MGMNT_TFK_CTL = 0x00000160, /* Set Mgmnt Traffic Control */ MB_SET_MPI_TFK_STOP = (1 << 0), MB_SET_MPI_TFK_RESUME = (1 << 1), @@ -1551,6 +1554,7 @@ struct ql_adapter { u32 port_init; u32 link_status; u32 link_config; + u32 led_config; u32 max_frame_size; union flash_params flash; @@ -1642,6 +1646,8 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev); int ql_cam_route_initialize(struct ql_adapter *qdev); int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); int ql_mb_about_fw(struct ql_adapter *qdev); +int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config); +int ql_mb_get_led_cfg(struct ql_adapter *qdev); void ql_link_on(struct ql_adapter *qdev); void ql_link_off(struct ql_adapter *qdev); int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control); diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index dfb5c800cea..0c0549bc7bd 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -371,6 +371,33 @@ static void ql_get_drvinfo(struct net_device *ndev, drvinfo->eedump_len = 0; } + +static int ql_phys_id(struct net_device *ndev, u32 data) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + u32 led_reg, i; + int status; + + /* Save the current LED settings */ + status = ql_mb_get_led_cfg(qdev); + if (status) + return status; + led_reg = qdev->led_config; + + /* Start blinking the led */ + if (!data || data > 300) + data = 300; + + for (i = 0; i < (data * 10); i++) + ql_mb_set_led_cfg(qdev, QL_LED_BLINK); + + /* Restore LED settings */ + status = ql_mb_set_led_cfg(qdev, led_reg); + if (status) + return status; + + return 0; +} static int ql_get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) { struct ql_adapter *qdev = netdev_priv(dev); @@ -499,6 +526,7 @@ const struct ethtool_ops qlge_ethtool_ops = { .get_msglevel = ql_get_msglevel, .set_msglevel = ql_set_msglevel, .get_link = ethtool_op_get_link, + .phys_id = ql_phys_id, .get_pauseparam = ql_get_pauseparam, .set_pauseparam = ql_set_pauseparam, .get_rx_csum = ql_get_rx_csum, diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 81a8489fe21..14d76f13d1d 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -751,6 +751,61 @@ static int ql_idc_wait(struct ql_adapter *qdev) return status; } +int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config) +{ + struct mbox_params mbc; + struct mbox_params *mbcp = &mbc; + int status; + + memset(mbcp, 0, sizeof(struct mbox_params)); + + mbcp->in_count = 2; + mbcp->out_count = 1; + + mbcp->mbox_in[0] = MB_CMD_SET_LED_CFG; + mbcp->mbox_in[1] = led_config; + + + status = ql_mailbox_command(qdev, mbcp); + if (status) + return status; + + if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { + QPRINTK(qdev, DRV, ERR, + "Failed to set LED Configuration.\n"); + status = -EIO; + } + + return status; +} + +int ql_mb_get_led_cfg(struct ql_adapter *qdev) +{ + struct mbox_params mbc; + struct mbox_params *mbcp = &mbc; + int status; + + memset(mbcp, 0, sizeof(struct mbox_params)); + + mbcp->in_count = 1; + mbcp->out_count = 2; + + mbcp->mbox_in[0] = MB_CMD_GET_LED_CFG; + + status = ql_mailbox_command(qdev, mbcp); + if (status) + return status; + + if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { + QPRINTK(qdev, DRV, ERR, + "Failed to get LED Configuration.\n"); + status = -EIO; + } else + qdev->led_config = mbcp->mbox_out[1]; + + return status; +} + int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control) { struct mbox_params mbc; -- cgit v1.2.3-70-g09d2 From bc083ce98eeb42205e99495481c8616d30916f6e Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 21 Oct 2009 11:07:40 +0000 Subject: qlge: Add ethtool wake on LAN function. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 4 +++ drivers/net/qlge/qlge_ethtool.c | 32 +++++++++++++++++++ drivers/net/qlge/qlge_main.c | 66 ++++++++++++++++++++++++++++++++++++++ drivers/net/qlge/qlge_mpi.c | 70 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+) (limited to 'drivers/net/qlge/qlge_mpi.c') diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index a5bb3a53653..ba297769920 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -796,6 +796,7 @@ enum { MB_WOL_BCAST = (1 << 5), MB_WOL_LINK_UP = (1 << 6), MB_WOL_LINK_DOWN = (1 << 7), + MB_WOL_MODE_ON = (1 << 16), /* Wake on Lan Mode on */ MB_CMD_SET_WOL_FLTR = 0x00000111, /* Wake On Lan Filter */ MB_CMD_CLEAR_WOL_FLTR = 0x00000112, /* Wake On Lan Filter */ MB_CMD_SET_WOL_MAGIC = 0x00000113, /* Wake On Lan Magic Packet */ @@ -1646,6 +1647,9 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev); int ql_cam_route_initialize(struct ql_adapter *qdev); int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); int ql_mb_about_fw(struct ql_adapter *qdev); +int ql_wol(struct ql_adapter *qdev); +int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol); +int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol); int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config); int ql_mb_get_led_cfg(struct ql_adapter *qdev); void ql_link_on(struct ql_adapter *qdev); diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 0c0549bc7bd..019f35fb10c 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -371,6 +371,36 @@ static void ql_get_drvinfo(struct net_device *ndev, drvinfo->eedump_len = 0; } +static void ql_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + /* What we support. */ + wol->supported = WAKE_MAGIC; + /* What we've currently got set. */ + wol->wolopts = qdev->wol; +} + +static int ql_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) +{ + struct ql_adapter *qdev = netdev_priv(ndev); + int status; + + if (wol->wolopts & ~WAKE_MAGIC) + return -EINVAL; + qdev->wol = wol->wolopts; + + QPRINTK(qdev, DRV, INFO, "Set wol option 0x%x on %s\n", + qdev->wol, ndev->name); + if (!qdev->wol) { + u32 wol = 0; + status = ql_mb_wol_mode(qdev, wol); + QPRINTK(qdev, DRV, ERR, "WOL %s (wol code 0x%x) on %s\n", + (status == 0) ? "cleared sucessfully" : "clear failed", + wol, qdev->ndev->name); + } + + return 0; +} static int ql_phys_id(struct net_device *ndev, u32 data) { @@ -523,6 +553,8 @@ static void ql_set_msglevel(struct net_device *ndev, u32 value) const struct ethtool_ops qlge_ethtool_ops = { .get_settings = ql_get_settings, .get_drvinfo = ql_get_drvinfo, + .get_wol = ql_get_wol, + .set_wol = ql_set_wol, .get_msglevel = ql_get_msglevel, .set_msglevel = ql_set_msglevel, .get_link = ethtool_op_get_link, diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 34242fbcadf..dd0ea027755 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3335,6 +3335,22 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) * the same MAC address. */ ql_write32(qdev, RST_FO, RST_FO_RR_MASK | RST_FO_RR_RCV_FUNC_CQ); + /* Reroute all packets to our Interface. + * They may have been routed to MPI firmware + * due to WOL. + */ + value = ql_read32(qdev, MGMT_RCV_CFG); + value &= ~MGMT_RCV_CFG_RM; + mask = 0xffff0000; + + /* Sticky reg needs clearing due to WOL. */ + ql_write32(qdev, MGMT_RCV_CFG, mask); + ql_write32(qdev, MGMT_RCV_CFG, mask | value); + + /* Default WOL is enable on Mezz cards */ + if (qdev->pdev->subsystem_device == 0x0068 || + qdev->pdev->subsystem_device == 0x0180) + qdev->wol = WAKE_MAGIC; /* Start up the rx queues. */ for (i = 0; i < qdev->rx_ring_count; i++) { @@ -3449,6 +3465,55 @@ static void ql_display_dev_info(struct net_device *ndev) QPRINTK(qdev, PROBE, INFO, "MAC address %pM\n", ndev->dev_addr); } +int ql_wol(struct ql_adapter *qdev) +{ + int status = 0; + u32 wol = MB_WOL_DISABLE; + + /* The CAM is still intact after a reset, but if we + * are doing WOL, then we may need to program the + * routing regs. We would also need to issue the mailbox + * commands to instruct the MPI what to do per the ethtool + * settings. + */ + + if (qdev->wol & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_PHY | WAKE_UCAST | + WAKE_MCAST | WAKE_BCAST)) { + QPRINTK(qdev, IFDOWN, ERR, + "Unsupported WOL paramter. qdev->wol = 0x%x.\n", + qdev->wol); + return -EINVAL; + } + + if (qdev->wol & WAKE_MAGIC) { + status = ql_mb_wol_set_magic(qdev, 1); + if (status) { + QPRINTK(qdev, IFDOWN, ERR, + "Failed to set magic packet on %s.\n", + qdev->ndev->name); + return status; + } else + QPRINTK(qdev, DRV, INFO, + "Enabled magic packet successfully on %s.\n", + qdev->ndev->name); + + wol |= MB_WOL_MAGIC_PKT; + } + + if (qdev->wol) { + /* Reroute all packets to Management Interface */ + ql_write32(qdev, MGMT_RCV_CFG, (MGMT_RCV_CFG_RM | + (MGMT_RCV_CFG_RM << 16))); + wol |= MB_WOL_MODE_ON; + status = ql_mb_wol_mode(qdev, wol); + QPRINTK(qdev, DRV, ERR, "WOL %s (wol code 0x%x) on %s\n", + (status == 0) ? "Sucessfully set" : "Failed", wol, + qdev->ndev->name); + } + + return status; +} + static int ql_adapter_down(struct ql_adapter *qdev) { int i, status = 0; @@ -4285,6 +4350,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) return err; } + ql_wol(qdev); err = pci_save_state(pdev); if (err) return err; diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 14d76f13d1d..80b68539c5a 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -702,6 +702,76 @@ int ql_mb_get_port_cfg(struct ql_adapter *qdev) return status; } +int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol) +{ + struct mbox_params mbc; + struct mbox_params *mbcp = &mbc; + int status; + + memset(mbcp, 0, sizeof(struct mbox_params)); + + mbcp->in_count = 2; + mbcp->out_count = 1; + + mbcp->mbox_in[0] = MB_CMD_SET_WOL_MODE; + mbcp->mbox_in[1] = wol; + + + status = ql_mailbox_command(qdev, mbcp); + if (status) + return status; + + if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { + QPRINTK(qdev, DRV, ERR, + "Failed to set WOL mode.\n"); + status = -EIO; + } + return status; +} + +int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol) +{ + struct mbox_params mbc; + struct mbox_params *mbcp = &mbc; + int status; + u8 *addr = qdev->ndev->dev_addr; + + memset(mbcp, 0, sizeof(struct mbox_params)); + + mbcp->in_count = 8; + mbcp->out_count = 1; + + mbcp->mbox_in[0] = MB_CMD_SET_WOL_MAGIC; + if (enable_wol) { + mbcp->mbox_in[1] = (u32)addr[0]; + mbcp->mbox_in[2] = (u32)addr[1]; + mbcp->mbox_in[3] = (u32)addr[2]; + mbcp->mbox_in[4] = (u32)addr[3]; + mbcp->mbox_in[5] = (u32)addr[4]; + mbcp->mbox_in[6] = (u32)addr[5]; + mbcp->mbox_in[7] = 0; + } else { + mbcp->mbox_in[1] = 0; + mbcp->mbox_in[2] = 1; + mbcp->mbox_in[3] = 1; + mbcp->mbox_in[4] = 1; + mbcp->mbox_in[5] = 1; + mbcp->mbox_in[6] = 1; + mbcp->mbox_in[7] = 0; + } + + status = ql_mailbox_command(qdev, mbcp); + if (status) + return status; + + if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { + QPRINTK(qdev, DRV, ERR, + "Failed to set WOL mode.\n"); + status = -EIO; + } + return status; +} + /* IDC - Inter Device Communication... * Some firmware commands require consent of adjacent FCOE * function. This function waits for the OK, or a -- cgit v1.2.3-70-g09d2 From 1e34e307d0ebe536feb39c957c849a485bc81486 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Tue, 3 Nov 2009 13:49:30 +0000 Subject: qlge: Add firmware/driver sub-command support. These sub-commands are issued by another (FCoE) function requesting an operation on a shared resource. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 12 ++++++++++ drivers/net/qlge/qlge_mpi.c | 56 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 7 deletions(-) (limited to 'drivers/net/qlge/qlge_mpi.c') diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 872e95ee40e..5e4d3439043 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -816,6 +816,18 @@ enum { MB_CMD_GET_MGMNT_TFK_CTL = 0x00000161, /* Get Mgmnt Traffic Control */ MB_GET_MPI_TFK_STOPPED = (1 << 0), MB_GET_MPI_TFK_FIFO_EMPTY = (1 << 1), + /* Sub-commands for IDC request. + * This describes the reason for the + * IDC request. + */ + MB_CMD_IOP_NONE = 0x0000, + MB_CMD_IOP_PREP_UPDATE_MPI = 0x0001, + MB_CMD_IOP_COMP_UPDATE_MPI = 0x0002, + MB_CMD_IOP_PREP_LINK_DOWN = 0x0010, + MB_CMD_IOP_DVR_START = 0x0100, + MB_CMD_IOP_FLASH_ACC = 0x0101, + MB_CMD_IOP_RESTART_MPI = 0x0102, + MB_CMD_IOP_CORE_DUMP_MPI = 0x0103, /* Mailbox Command Status. */ MB_CMD_STS_GOOD = 0x00004000, /* Success. */ diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index bac7b86f212..f5619fe87bb 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -1038,8 +1038,11 @@ void ql_mpi_idc_work(struct work_struct *work) int status; struct mbox_params *mbcp = &qdev->idc_mbc; u32 aen; + int timeout; + rtnl_lock(); aen = mbcp->mbox_out[1] >> 16; + timeout = (mbcp->mbox_out[1] >> 8) & 0xf; switch (aen) { default: @@ -1047,22 +1050,61 @@ void ql_mpi_idc_work(struct work_struct *work) "Bug: Unhandled IDC action.\n"); break; case MB_CMD_PORT_RESET: - case MB_CMD_SET_PORT_CFG: case MB_CMD_STOP_FW: ql_link_off(qdev); + case MB_CMD_SET_PORT_CFG: /* Signal the resulting link up AEN * that the frame routing and mac addr * needs to be set. * */ set_bit(QL_CAM_RT_SET, &qdev->flags); - rtnl_lock(); - status = ql_mb_idc_ack(qdev); - rtnl_unlock(); - if (status) { - QPRINTK(qdev, DRV, ERR, - "Bug: No pending IDC!\n"); + /* Do ACK if required */ + if (timeout) { + status = ql_mb_idc_ack(qdev); + if (status) + QPRINTK(qdev, DRV, ERR, + "Bug: No pending IDC!\n"); + } else { + QPRINTK(qdev, DRV, DEBUG, + "IDC ACK not required\n"); + status = 0; /* success */ + } + break; + + /* These sub-commands issued by another (FCoE) + * function are requesting to do an operation + * on the shared resource (MPI environment). + * We currently don't issue these so we just + * ACK the request. + */ + case MB_CMD_IOP_RESTART_MPI: + case MB_CMD_IOP_PREP_LINK_DOWN: + /* Drop the link, reload the routing + * table when link comes up. + */ + ql_link_off(qdev); + set_bit(QL_CAM_RT_SET, &qdev->flags); + /* Fall through. */ + case MB_CMD_IOP_DVR_START: + case MB_CMD_IOP_FLASH_ACC: + case MB_CMD_IOP_CORE_DUMP_MPI: + case MB_CMD_IOP_PREP_UPDATE_MPI: + case MB_CMD_IOP_COMP_UPDATE_MPI: + case MB_CMD_IOP_NONE: /* an IDC without params */ + /* Do ACK if required */ + if (timeout) { + status = ql_mb_idc_ack(qdev); + if (status) + QPRINTK(qdev, DRV, ERR, + "Bug: No pending IDC!\n"); + } else { + QPRINTK(qdev, DRV, DEBUG, + "IDC ACK not required\n"); + status = 0; /* success */ } + break; } + rtnl_unlock(); } void ql_mpi_work(struct work_struct *work) -- cgit v1.2.3-70-g09d2