#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.3"
+#define DRV_VERSION "1.4"
#define PFX DRV_NAME " "
/*
}
if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON);
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
reg1 &= P_ASPM_CONTROL_MSK;
u16 ctrl, ct1000, adv, pg, ledctrl, ledover;
if (sky2->autoneg == AUTONEG_ENABLE &&
- (hw->chip_id != CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) {
+ !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
struct sky2_hw *hw = sky2->hw;
unsigned rxq = rxqaddr[sky2->port];
int i;
+ unsigned thresh;
sky2->rx_put = sky2->rx_next = 0;
sky2_qset(hw, rxq);
sky2_rx_add(sky2, re->mapaddr);
}
- /* Truncate oversize frames */
- sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize - 8);
- sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
+
+ /*
+ * The receiver hangs if it receives frames larger than the
+ * packet buffer. As a workaround, truncate oversize frames, but
+ * the register is limited to 9 bits, so if you do frames > 2052
+ * you better get the MTU right!
+ */
+ thresh = (sky2->rx_bufsize - 8) / sizeof(u32);
+ if (thresh > 0x1ff)
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF);
+ else {
+ sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh);
+ sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON);
+ }
+
/* Tell chip about available buffers */
sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put);
}
}
+/* Is status ring empty or is there more to do? */
+static inline int sky2_more_work(const struct sky2_hw *hw)
+{
+ return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX));
+}
+
/* Process status response ring */
static int sky2_status_intr(struct sky2_hw *hw, int to_do)
{
if (status & Y2_IS_CHK_TXA2)
sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
- if (status & Y2_IS_STAT_BMU)
- sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-
work_done = sky2_status_intr(hw, work_limit);
*budget -= work_done;
dev0->quota -= work_done;
- if (work_done >= work_limit)
+ if (status & Y2_IS_STAT_BMU)
+ sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
+ if (sky2_more_work(hw))
return 1;
netif_rx_complete(dev0);
- status = sky2_read32(hw, B0_Y2_SP_LISR);
+ sky2_read32(hw, B0_Y2_SP_LISR);
return 0;
}