mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
Fix several RUTX issues
This commit is contained in:
parent
41f999557f
commit
66eed314b7
8 changed files with 1424 additions and 0 deletions
|
@ -0,0 +1,16 @@
|
|||
Index: linux-5.4.124/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
===================================================================
|
||||
--- linux-5.4.124.orig/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
+++ linux-5.4.124/arch/arm/boot/dts/qcom-ipq4019.dtsi
|
||||
@@ -140,9 +140,9 @@
|
||||
};
|
||||
|
||||
clocks {
|
||||
- sleep_clk: sleep_clk {
|
||||
+ sleep_clk: gcc_sleep_clk_src {
|
||||
compatible = "fixed-clock";
|
||||
- clock-frequency = <32768>;
|
||||
+ clock-frequency = <32000>;
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
--- a/fs/jffs2/writev.c
|
||||
+++ b/fs/jffs2/writev.c
|
||||
@@ -16,9 +16,18 @@
|
||||
int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
|
||||
unsigned long count, loff_t to, size_t *retlen)
|
||||
{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = mtd_writev(c->mtd, vecs, count, to, retlen);
|
||||
+
|
||||
if (!jffs2_is_writebuffered(c)) {
|
||||
if (jffs2_sum_active()) {
|
||||
int res;
|
||||
+
|
||||
+ if (ret ||
|
||||
+ *retlen != iov_length((struct iovec *) vecs, count))
|
||||
+ return ret;
|
||||
+
|
||||
res = jffs2_sum_add_kvec(c, vecs, count, (uint32_t) to);
|
||||
if (res) {
|
||||
return res;
|
||||
@@ -26,18 +35,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
- return mtd_writev(c->mtd, vecs, count, to, retlen);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
|
||||
size_t *retlen, const u_char *buf)
|
||||
{
|
||||
int ret;
|
||||
+
|
||||
ret = mtd_write(c->mtd, ofs, len, retlen, buf);
|
||||
|
||||
if (jffs2_sum_active()) {
|
||||
struct kvec vecs[1];
|
||||
int res;
|
||||
+
|
||||
+ if (ret || *retlen != len)
|
||||
+ return ret;
|
||||
|
||||
vecs[0].iov_base = (unsigned char *) buf;
|
||||
vecs[0].iov_len = len;
|
||||
@@ -47,5 +60,6 @@
|
||||
return res;
|
||||
}
|
||||
}
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
--- a/drivers/net/phy/qca807x.c
|
||||
+++ b/drivers/net/phy/qca807x.c
|
||||
@@ -122,9 +122,24 @@
|
||||
#define PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK GENMASK(3, 0)
|
||||
#define PSGMII_MMD3_SERDES_CONTROL 0x805a
|
||||
|
||||
+#define QCA8075_PHY4_PREFER_FIBER 0x400
|
||||
+
|
||||
struct qca807x_gpio_priv {
|
||||
struct phy_device *phy;
|
||||
};
|
||||
+
|
||||
+/* Phy medium type */
|
||||
+typedef enum {
|
||||
+ QCA8075_PHY_MEDIUM_COPPER = 0,
|
||||
+ QCA8075_PHY_MEDIUM_FIBER = 1, /**< Fiber */
|
||||
+ QCA8075_PHY_MEDIUM_NULL = 2 /**< NULL */
|
||||
+} qca8075_phy_medium_t;
|
||||
+
|
||||
+static qca8075_phy_medium_t last_phy_medium = QCA8075_PHY_MEDIUM_NULL;
|
||||
+static int last_phydev_link_state = -1;
|
||||
+static int copper_link = 0;
|
||||
+static int fiber_link = 0;
|
||||
+static int report_last_status = 0;
|
||||
|
||||
static int qca807x_get_downshift(struct phy_device *phydev, u8 *data)
|
||||
{
|
||||
@@ -400,6 +415,142 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
+static qca8075_phy_medium_t phy_prefer_medium_get(struct phy_device *phydev)
|
||||
+{
|
||||
+ int val;
|
||||
+ val = phy_read(phydev, QCA807X_CHIP_CONFIGURATION);
|
||||
+
|
||||
+ return ((val & QCA8075_PHY4_PREFER_FIBER) ?
|
||||
+ QCA8075_PHY_MEDIUM_FIBER : QCA8075_PHY_MEDIUM_COPPER);
|
||||
+}
|
||||
+
|
||||
+static qca8075_phy_medium_t phy_active_medium_get(struct phy_device *phydev) {
|
||||
+ int val;
|
||||
+ val = phy_read(phydev, QCA807X_MEDIA_SELECT_STATUS);
|
||||
+
|
||||
+ if (val & QCA807X_MEDIA_DETECTED_COPPER) {
|
||||
+ return QCA8075_PHY_MEDIUM_COPPER;
|
||||
+ } else if ((val & QCA807X_MEDIA_DETECTED_1000_BASE_X) ||
|
||||
+ (val & QCA807X_MEDIA_DETECTED_100_BASE_FX)) {
|
||||
+ return QCA8075_PHY_MEDIUM_FIBER;
|
||||
+ } else {
|
||||
+ return phy_prefer_medium_get(phydev);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int ar40xx_update_link(struct phy_device *phydev)
|
||||
+{
|
||||
+ int status = 0, bmcr;
|
||||
+ qca8075_phy_medium_t phy_medium;
|
||||
+
|
||||
+ phy_medium = phy_active_medium_get(phydev);
|
||||
+
|
||||
+ /* Do a fake read */
|
||||
+ bmcr = phy_read(phydev, MII_BMSR);
|
||||
+ if (bmcr < 0)
|
||||
+ return bmcr;
|
||||
+
|
||||
+ /* Autoneg is being started, therefore disregard BMSR value and
|
||||
+ * report link as down.
|
||||
+ */
|
||||
+ if (bmcr & BMCR_ANRESTART)
|
||||
+ goto done;
|
||||
+
|
||||
+ /* The link state is latched low so that momentary link
|
||||
+ * drops can be detected. Do not double-read the status
|
||||
+ * in polling mode to detect such short link drops except
|
||||
+ * the link was already down.
|
||||
+ */
|
||||
+ if (!phy_polling_mode(phydev) || !phydev->link) {
|
||||
+ status = phy_read(phydev, MII_BMSR);
|
||||
+ if (status < 0)
|
||||
+ return status;
|
||||
+ else if (status & BMSR_LSTATUS)
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ /* Read link and autonegotiation status */
|
||||
+ status = phy_read(phydev, MII_BMSR);
|
||||
+ if (status < 0)
|
||||
+ return status;
|
||||
+done:
|
||||
+ if ( report_last_status > 0 ) {
|
||||
+ report_last_status = 0;
|
||||
+ phydev->link = last_phydev_link_state;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ /* reporting copper/fiber link state to netdev */
|
||||
+ if ((status & BMSR_LSTATUS) == 0) {
|
||||
+ phydev->link = 0;
|
||||
+ if (last_phy_medium == phy_medium) { /* medium not changed */
|
||||
+ if(phydev->link != last_phydev_link_state)
|
||||
+ report_last_status++;
|
||||
+ if (phy_medium == QCA8075_PHY_MEDIUM_FIBER)
|
||||
+ fiber_link = 0;
|
||||
+ else
|
||||
+ copper_link = 0;
|
||||
+ } else { /* medium changed, check current medium*/
|
||||
+ if (phy_medium == QCA8075_PHY_MEDIUM_FIBER) { /* fiber active*/
|
||||
+ if (copper_link == 1) { /* copper active, but not preferred*/
|
||||
+ if(phydev->link == last_phydev_link_state) {
|
||||
+ phydev->link = !phydev->link; /* toggle link state */
|
||||
+ report_last_status++;
|
||||
+ }
|
||||
+ }
|
||||
+ fiber_link = 0;
|
||||
+ } else { /* copper active*/
|
||||
+ if (fiber_link == 1) { /* fiber active, preferred*/
|
||||
+ if(phydev->link == last_phydev_link_state) {
|
||||
+ phydev->link = !phydev->link; /* toggle link state */
|
||||
+ report_last_status++;
|
||||
+ }
|
||||
+ }
|
||||
+ copper_link = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ phydev->link = 1;
|
||||
+ if (last_phy_medium == phy_medium){
|
||||
+ if (phy_medium == QCA8075_PHY_MEDIUM_FIBER)
|
||||
+ fiber_link = 1;
|
||||
+ else
|
||||
+ copper_link = 1;
|
||||
+ }
|
||||
+ else {
|
||||
+ if (phy_medium == QCA8075_PHY_MEDIUM_FIBER) { /* fiber active*/
|
||||
+ if (copper_link == 1) { /* copper active, but not preferred*/
|
||||
+ if(phydev->link == last_phydev_link_state) {
|
||||
+ phydev->link = !phydev->link;
|
||||
+ report_last_status++;
|
||||
+ }
|
||||
+ }
|
||||
+ fiber_link = 1;
|
||||
+ } else { /* copper active*/
|
||||
+ if (fiber_link == 1) { /* fiber active, preferred*/
|
||||
+ if(phydev->link == last_phydev_link_state) {
|
||||
+ phydev->link = !phydev->link;
|
||||
+ report_last_status++;
|
||||
+ }
|
||||
+ }
|
||||
+ copper_link = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ phydev->autoneg_complete = status & BMSR_ANEGCOMPLETE ? 1 : 0;
|
||||
+
|
||||
+ /* Consider the case that autoneg was started and "aneg complete"
|
||||
+ * bit has been reset, but "link up" bit not yet.
|
||||
+ */
|
||||
+ if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
|
||||
+ phydev->link = 0;
|
||||
+
|
||||
+ last_phy_medium = phy_medium;
|
||||
+ last_phydev_link_state = phydev->link;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int qca807x_read_copper_status(struct phy_device *phydev, bool combo_port)
|
||||
{
|
||||
int ss, err, page, old_link = phydev->link;
|
||||
@@ -415,7 +566,7 @@
|
||||
}
|
||||
|
||||
/* Update the link, but return if there was an error */
|
||||
- err = genphy_update_link(phydev);
|
||||
+ err = ar40xx_update_link(phydev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -499,7 +650,7 @@
|
||||
}
|
||||
|
||||
/* Update the link, but return if there was an error */
|
||||
- err = genphy_update_link(phydev);
|
||||
+ err = ar40xx_update_link(phydev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -559,7 +710,7 @@
|
||||
|
||||
static int qca807x_read_status(struct phy_device *phydev)
|
||||
{
|
||||
- int val;
|
||||
+ int val, err;
|
||||
|
||||
/* Check for Combo port */
|
||||
if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) {
|
||||
@@ -572,6 +723,11 @@
|
||||
} else if ((val & QCA807X_MEDIA_DETECTED_1000_BASE_X) ||
|
||||
(val & QCA807X_MEDIA_DETECTED_100_BASE_FX)) {
|
||||
qca807x_read_fiber_status(phydev, true);
|
||||
+ } else {
|
||||
+ /* Update the link, but return if there was an error */
|
||||
+ err = ar40xx_update_link(phydev);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
}
|
||||
} else {
|
||||
qca807x_read_copper_status(phydev, true);
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
Index: linux-5.4.137/drivers/usb/serial/option.c
|
||||
===================================================================
|
||||
--- linux-5.4.137.orig/drivers/usb/serial/option.c
|
||||
+++ linux-5.4.137/drivers/usb/serial/option.c
|
||||
@@ -241,6 +241,8 @@ static void option_instat_callback(struc
|
||||
#define UBLOX_PRODUCT_R6XX 0x90fa
|
||||
/* These Yuga products use Qualcomm's vendor ID */
|
||||
#define YUGA_PRODUCT_CLM920_NC5 0x9625
|
||||
+/* These Meiglink products use Qualcomm's vendor ID */
|
||||
+#define MEIGLINK_PRODUCT_SLM750 0xf601
|
||||
|
||||
#define QUECTEL_VENDOR_ID 0x2c7c
|
||||
/* These Quectel products use Quectel's vendor ID */
|
||||
@@ -1102,6 +1104,9 @@ static const struct usb_device_id option
|
||||
/* u-blox products using Qualcomm vendor ID */
|
||||
{ USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R410M),
|
||||
.driver_info = RSVD(1) | RSVD(3) },
|
||||
+ /* Meiglink products using Qualcomm vendor ID */
|
||||
+ // Works OK in case of some issues check macros that are used by Quectel Products
|
||||
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, MEIGLINK_PRODUCT_SLM750)},
|
||||
{ USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R6XX),
|
||||
.driver_info = RSVD(3) },
|
||||
/* Quectel products using Quectel vendor ID */
|
||||
Index: linux-5.4.137/drivers/net/usb/qmi_wwan.c
|
||||
===================================================================
|
||||
--- linux-5.4.137.orig/drivers/net/usb/qmi_wwan.c
|
||||
+++ linux-5.4.137/drivers/net/usb/qmi_wwan.c
|
||||
@@ -1171,6 +1171,7 @@ static const struct usb_device_id produc
|
||||
{QMI_FIXED_INTF(0x05c6, 0x9079, 6)},
|
||||
{QMI_FIXED_INTF(0x05c6, 0x9079, 7)},
|
||||
{QMI_FIXED_INTF(0x05c6, 0x9079, 8)},
|
||||
+ {QMI_MATCH_FF_FF_FF(0x05c6, 0xf601)}, /* Meiglink SLM750 (in case of issues check if DTR flag setting is enough) */
|
||||
{QMI_FIXED_INTF(0x05c6, 0x9080, 5)},
|
||||
{QMI_FIXED_INTF(0x05c6, 0x9080, 6)},
|
||||
{QMI_FIXED_INTF(0x05c6, 0x9080, 7)},
|
|
@ -0,0 +1,105 @@
|
|||
--- a/drivers/spi/spi-qup.c
|
||||
+++ b/drivers/spi/spi-qup.c
|
||||
@@ -273,9 +273,6 @@
|
||||
writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
|
||||
controller->base + QUP_OPERATIONAL);
|
||||
|
||||
- if (!remainder)
|
||||
- goto exit;
|
||||
-
|
||||
if (is_block_mode) {
|
||||
num_words = (remainder > words_per_block) ?
|
||||
words_per_block : remainder;
|
||||
@@ -305,13 +302,11 @@
|
||||
* to refresh opflags value because MAX_INPUT_DONE_FLAG may now be
|
||||
* present and this is used to determine if transaction is complete
|
||||
*/
|
||||
-exit:
|
||||
- if (!remainder) {
|
||||
- *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
|
||||
- if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
|
||||
- writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
|
||||
- controller->base + QUP_OPERATIONAL);
|
||||
- }
|
||||
+ *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
|
||||
+ if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
|
||||
+ writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
|
||||
+ controller->base + QUP_OPERATIONAL);
|
||||
+
|
||||
}
|
||||
|
||||
static void spi_qup_write_to_fifo(struct spi_qup *controller, u32 num_words)
|
||||
@@ -358,10 +353,6 @@
|
||||
/* ACK by clearing service flag */
|
||||
writel_relaxed(QUP_OP_OUT_SERVICE_FLAG,
|
||||
controller->base + QUP_OPERATIONAL);
|
||||
-
|
||||
- /* make sure the interrupt is valid */
|
||||
- if (!remainder)
|
||||
- return;
|
||||
|
||||
if (is_block_mode) {
|
||||
num_words = (remainder > words_per_block) ?
|
||||
@@ -576,24 +567,10 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static bool spi_qup_data_pending(struct spi_qup *controller)
|
||||
-{
|
||||
- unsigned int remainder_tx, remainder_rx;
|
||||
-
|
||||
- remainder_tx = DIV_ROUND_UP(spi_qup_len(controller) -
|
||||
- controller->tx_bytes, controller->w_size);
|
||||
-
|
||||
- remainder_rx = DIV_ROUND_UP(spi_qup_len(controller) -
|
||||
- controller->rx_bytes, controller->w_size);
|
||||
-
|
||||
- return remainder_tx || remainder_rx;
|
||||
-}
|
||||
-
|
||||
static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct spi_qup *controller = dev_id;
|
||||
u32 opflags, qup_err, spi_err;
|
||||
- unsigned long flags;
|
||||
int error = 0;
|
||||
|
||||
qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS);
|
||||
@@ -625,11 +602,6 @@
|
||||
error = -EIO;
|
||||
}
|
||||
|
||||
- spin_lock_irqsave(&controller->lock, flags);
|
||||
- if (!controller->error)
|
||||
- controller->error = error;
|
||||
- spin_unlock_irqrestore(&controller->lock, flags);
|
||||
-
|
||||
if (spi_qup_is_dma_xfer(controller->mode)) {
|
||||
writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
|
||||
} else {
|
||||
@@ -638,21 +610,10 @@
|
||||
|
||||
if (opflags & QUP_OP_OUT_SERVICE_FLAG)
|
||||
spi_qup_write(controller);
|
||||
-
|
||||
- if (!spi_qup_data_pending(controller))
|
||||
- complete(&controller->done);
|
||||
- }
|
||||
-
|
||||
- if (error)
|
||||
+ }
|
||||
+
|
||||
+ if ((opflags & QUP_OP_MAX_INPUT_DONE_FLAG) || error)
|
||||
complete(&controller->done);
|
||||
-
|
||||
- if (opflags & QUP_OP_MAX_INPUT_DONE_FLAG) {
|
||||
- if (!spi_qup_is_dma_xfer(controller->mode)) {
|
||||
- if (spi_qup_data_pending(controller))
|
||||
- return IRQ_HANDLED;
|
||||
- }
|
||||
- complete(&controller->done);
|
||||
- }
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue