Commit 22726020 authored by Marek Vasut's avatar Marek Vasut Committed by David S. Miller

net: ks8851: Factor out bus lock handling

Pull out bus access locking code into separate functions, this is done
in preparation for unifying the driver with the parallel bus one. The
parallel bus driver does not need heavy mutex locking of the bus and
works better with spinlocks, hence prepare these locking functions to
be overridden then.
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarMarek Vasut <marex@denx.de>
Cc: David S. Miller <davem@davemloft.net>
Cc: Lukas Wunner <lukas@wunner.de>
Cc: Petr Stetiar <ynezz@true.cz>
Cc: YueHaibing <yuehaibing@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent aa39bf67
...@@ -151,6 +151,30 @@ static int msg_enable; ...@@ -151,6 +151,30 @@ static int msg_enable;
/* turn register number and byte-enable mask into data for start of packet */ /* turn register number and byte-enable mask into data for start of packet */
#define MK_OP(_byteen, _reg) (BYTE_EN(_byteen) | (_reg) << (8+2) | (_reg) >> 6) #define MK_OP(_byteen, _reg) (BYTE_EN(_byteen) | (_reg) << (8+2) | (_reg) >> 6)
/**
* ks8851_lock - register access lock
* @ks: The chip state
* @flags: Spinlock flags
*
* Claim chip register access lock
*/
static void ks8851_lock(struct ks8851_net *ks, unsigned long *flags)
{
mutex_lock(&ks->lock);
}
/**
* ks8851_unlock - register access unlock
* @ks: The chip state
* @flags: Spinlock flags
*
* Release chip register access lock
*/
static void ks8851_unlock(struct ks8851_net *ks, unsigned long *flags)
{
mutex_unlock(&ks->lock);
}
/* SPI register read/write calls. /* SPI register read/write calls.
* *
* All these calls issue SPI transactions to access the chip's registers. They * All these calls issue SPI transactions to access the chip's registers. They
...@@ -304,10 +328,11 @@ static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode) ...@@ -304,10 +328,11 @@ static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode)
static int ks8851_write_mac_addr(struct net_device *dev) static int ks8851_write_mac_addr(struct net_device *dev)
{ {
struct ks8851_net *ks = netdev_priv(dev); struct ks8851_net *ks = netdev_priv(dev);
unsigned long flags;
u16 val; u16 val;
int i; int i;
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
/* /*
* Wake up chip in case it was powered off when stopped; otherwise, * Wake up chip in case it was powered off when stopped; otherwise,
...@@ -323,7 +348,7 @@ static int ks8851_write_mac_addr(struct net_device *dev) ...@@ -323,7 +348,7 @@ static int ks8851_write_mac_addr(struct net_device *dev)
if (!netif_running(dev)) if (!netif_running(dev))
ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
return 0; return 0;
} }
...@@ -337,10 +362,11 @@ static int ks8851_write_mac_addr(struct net_device *dev) ...@@ -337,10 +362,11 @@ static int ks8851_write_mac_addr(struct net_device *dev)
static void ks8851_read_mac_addr(struct net_device *dev) static void ks8851_read_mac_addr(struct net_device *dev)
{ {
struct ks8851_net *ks = netdev_priv(dev); struct ks8851_net *ks = netdev_priv(dev);
unsigned long flags;
u16 reg; u16 reg;
int i; int i;
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
for (i = 0; i < ETH_ALEN; i += 2) { for (i = 0; i < ETH_ALEN; i += 2) {
reg = ks8851_rdreg16(ks, KS_MAR(i)); reg = ks8851_rdreg16(ks, KS_MAR(i));
...@@ -348,7 +374,7 @@ static void ks8851_read_mac_addr(struct net_device *dev) ...@@ -348,7 +374,7 @@ static void ks8851_read_mac_addr(struct net_device *dev)
dev->dev_addr[i + 1] = reg & 0xff; dev->dev_addr[i + 1] = reg & 0xff;
} }
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
} }
/** /**
...@@ -534,10 +560,11 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) ...@@ -534,10 +560,11 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
static irqreturn_t ks8851_irq(int irq, void *_ks) static irqreturn_t ks8851_irq(int irq, void *_ks)
{ {
struct ks8851_net *ks = _ks; struct ks8851_net *ks = _ks;
unsigned status;
unsigned handled = 0; unsigned handled = 0;
unsigned long flags;
unsigned int status;
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
status = ks8851_rdreg16(ks, KS_ISR); status = ks8851_rdreg16(ks, KS_ISR);
...@@ -606,7 +633,7 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) ...@@ -606,7 +633,7 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
ks8851_wrreg16(ks, KS_RXCR1, rxc->rxcr1); ks8851_wrreg16(ks, KS_RXCR1, rxc->rxcr1);
} }
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
if (status & IRQ_LCI) if (status & IRQ_LCI)
mii_check_link(&ks->mii); mii_check_link(&ks->mii);
...@@ -700,10 +727,11 @@ static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb) ...@@ -700,10 +727,11 @@ static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb)
static void ks8851_tx_work(struct work_struct *work) static void ks8851_tx_work(struct work_struct *work)
{ {
struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_work); struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_work);
unsigned long flags;
struct sk_buff *txb; struct sk_buff *txb;
bool last = skb_queue_empty(&ks->txq); bool last = skb_queue_empty(&ks->txq);
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
while (!last) { while (!last) {
txb = skb_dequeue(&ks->txq); txb = skb_dequeue(&ks->txq);
...@@ -719,7 +747,7 @@ static void ks8851_tx_work(struct work_struct *work) ...@@ -719,7 +747,7 @@ static void ks8851_tx_work(struct work_struct *work)
} }
} }
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
} }
/** /**
...@@ -732,6 +760,7 @@ static void ks8851_tx_work(struct work_struct *work) ...@@ -732,6 +760,7 @@ static void ks8851_tx_work(struct work_struct *work)
static int ks8851_net_open(struct net_device *dev) static int ks8851_net_open(struct net_device *dev)
{ {
struct ks8851_net *ks = netdev_priv(dev); struct ks8851_net *ks = netdev_priv(dev);
unsigned long flags;
int ret; int ret;
ret = request_threaded_irq(dev->irq, NULL, ks8851_irq, ret = request_threaded_irq(dev->irq, NULL, ks8851_irq,
...@@ -744,7 +773,7 @@ static int ks8851_net_open(struct net_device *dev) ...@@ -744,7 +773,7 @@ static int ks8851_net_open(struct net_device *dev)
/* lock the card, even if we may not actually be doing anything /* lock the card, even if we may not actually be doing anything
* else at the moment */ * else at the moment */
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
netif_dbg(ks, ifup, ks->netdev, "opening\n"); netif_dbg(ks, ifup, ks->netdev, "opening\n");
...@@ -804,7 +833,7 @@ static int ks8851_net_open(struct net_device *dev) ...@@ -804,7 +833,7 @@ static int ks8851_net_open(struct net_device *dev)
netif_dbg(ks, ifup, ks->netdev, "network device up\n"); netif_dbg(ks, ifup, ks->netdev, "network device up\n");
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
mii_check_link(&ks->mii); mii_check_link(&ks->mii);
return 0; return 0;
} }
...@@ -820,22 +849,23 @@ static int ks8851_net_open(struct net_device *dev) ...@@ -820,22 +849,23 @@ static int ks8851_net_open(struct net_device *dev)
static int ks8851_net_stop(struct net_device *dev) static int ks8851_net_stop(struct net_device *dev)
{ {
struct ks8851_net *ks = netdev_priv(dev); struct ks8851_net *ks = netdev_priv(dev);
unsigned long flags;
netif_info(ks, ifdown, dev, "shutting down\n"); netif_info(ks, ifdown, dev, "shutting down\n");
netif_stop_queue(dev); netif_stop_queue(dev);
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
/* turn off the IRQs and ack any outstanding */ /* turn off the IRQs and ack any outstanding */
ks8851_wrreg16(ks, KS_IER, 0x0000); ks8851_wrreg16(ks, KS_IER, 0x0000);
ks8851_wrreg16(ks, KS_ISR, 0xffff); ks8851_wrreg16(ks, KS_ISR, 0xffff);
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
/* stop any outstanding work */ /* stop any outstanding work */
flush_work(&ks->tx_work); flush_work(&ks->tx_work);
flush_work(&ks->rxctrl_work); flush_work(&ks->rxctrl_work);
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
/* shutdown RX process */ /* shutdown RX process */
ks8851_wrreg16(ks, KS_RXCR1, 0x0000); ks8851_wrreg16(ks, KS_RXCR1, 0x0000);
...@@ -844,7 +874,7 @@ static int ks8851_net_stop(struct net_device *dev) ...@@ -844,7 +874,7 @@ static int ks8851_net_stop(struct net_device *dev)
/* set powermode to soft power down to save power */ /* set powermode to soft power down to save power */
ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
/* ensure any queued tx buffers are dumped */ /* ensure any queued tx buffers are dumped */
while (!skb_queue_empty(&ks->txq)) { while (!skb_queue_empty(&ks->txq)) {
...@@ -916,13 +946,14 @@ static netdev_tx_t ks8851_start_xmit(struct sk_buff *skb, ...@@ -916,13 +946,14 @@ static netdev_tx_t ks8851_start_xmit(struct sk_buff *skb,
static void ks8851_rxctrl_work(struct work_struct *work) static void ks8851_rxctrl_work(struct work_struct *work)
{ {
struct ks8851_net *ks = container_of(work, struct ks8851_net, rxctrl_work); struct ks8851_net *ks = container_of(work, struct ks8851_net, rxctrl_work);
unsigned long flags;
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
/* need to shutdown RXQ before modifying filter parameters */ /* need to shutdown RXQ before modifying filter parameters */
ks8851_wrreg16(ks, KS_RXCR1, 0x00); ks8851_wrreg16(ks, KS_RXCR1, 0x00);
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
} }
static void ks8851_set_rx_mode(struct net_device *dev) static void ks8851_set_rx_mode(struct net_device *dev)
...@@ -1104,11 +1135,6 @@ static void ks8851_eeprom_regwrite(struct eeprom_93cx6 *ee) ...@@ -1104,11 +1135,6 @@ static void ks8851_eeprom_regwrite(struct eeprom_93cx6 *ee)
*/ */
static int ks8851_eeprom_claim(struct ks8851_net *ks) static int ks8851_eeprom_claim(struct ks8851_net *ks)
{ {
if (!(ks->rc_ccr & CCR_EEPROM))
return -ENOENT;
mutex_lock(&ks->lock);
/* start with clock low, cs high */ /* start with clock low, cs high */
ks8851_wrreg16(ks, KS_EEPCR, EEPCR_EESA | EEPCR_EECS); ks8851_wrreg16(ks, KS_EEPCR, EEPCR_EESA | EEPCR_EECS);
return 0; return 0;
...@@ -1125,7 +1151,6 @@ static void ks8851_eeprom_release(struct ks8851_net *ks) ...@@ -1125,7 +1151,6 @@ static void ks8851_eeprom_release(struct ks8851_net *ks)
unsigned val = ks8851_rdreg16(ks, KS_EEPCR); unsigned val = ks8851_rdreg16(ks, KS_EEPCR);
ks8851_wrreg16(ks, KS_EEPCR, val & ~EEPCR_EESA); ks8851_wrreg16(ks, KS_EEPCR, val & ~EEPCR_EESA);
mutex_unlock(&ks->lock);
} }
#define KS_EEPROM_MAGIC (0x00008851) #define KS_EEPROM_MAGIC (0x00008851)
...@@ -1135,6 +1160,7 @@ static int ks8851_set_eeprom(struct net_device *dev, ...@@ -1135,6 +1160,7 @@ static int ks8851_set_eeprom(struct net_device *dev,
{ {
struct ks8851_net *ks = netdev_priv(dev); struct ks8851_net *ks = netdev_priv(dev);
int offset = ee->offset; int offset = ee->offset;
unsigned long flags;
int len = ee->len; int len = ee->len;
u16 tmp; u16 tmp;
...@@ -1145,9 +1171,13 @@ static int ks8851_set_eeprom(struct net_device *dev, ...@@ -1145,9 +1171,13 @@ static int ks8851_set_eeprom(struct net_device *dev,
if (ee->magic != KS_EEPROM_MAGIC) if (ee->magic != KS_EEPROM_MAGIC)
return -EINVAL; return -EINVAL;
if (ks8851_eeprom_claim(ks)) if (!(ks->rc_ccr & CCR_EEPROM))
return -ENOENT; return -ENOENT;
ks8851_lock(ks, &flags);
ks8851_eeprom_claim(ks);
eeprom_93cx6_wren(&ks->eeprom, true); eeprom_93cx6_wren(&ks->eeprom, true);
/* ethtool currently only supports writing bytes, which means /* ethtool currently only supports writing bytes, which means
...@@ -1167,6 +1197,7 @@ static int ks8851_set_eeprom(struct net_device *dev, ...@@ -1167,6 +1197,7 @@ static int ks8851_set_eeprom(struct net_device *dev,
eeprom_93cx6_wren(&ks->eeprom, false); eeprom_93cx6_wren(&ks->eeprom, false);
ks8851_eeprom_release(ks); ks8851_eeprom_release(ks);
ks8851_unlock(ks, &flags);
return 0; return 0;
} }
...@@ -1176,19 +1207,25 @@ static int ks8851_get_eeprom(struct net_device *dev, ...@@ -1176,19 +1207,25 @@ static int ks8851_get_eeprom(struct net_device *dev,
{ {
struct ks8851_net *ks = netdev_priv(dev); struct ks8851_net *ks = netdev_priv(dev);
int offset = ee->offset; int offset = ee->offset;
unsigned long flags;
int len = ee->len; int len = ee->len;
/* must be 2 byte aligned */ /* must be 2 byte aligned */
if (len & 1 || offset & 1) if (len & 1 || offset & 1)
return -EINVAL; return -EINVAL;
if (ks8851_eeprom_claim(ks)) if (!(ks->rc_ccr & CCR_EEPROM))
return -ENOENT; return -ENOENT;
ks8851_lock(ks, &flags);
ks8851_eeprom_claim(ks);
ee->magic = KS_EEPROM_MAGIC; ee->magic = KS_EEPROM_MAGIC;
eeprom_93cx6_multiread(&ks->eeprom, offset/2, (__le16 *)data, len/2); eeprom_93cx6_multiread(&ks->eeprom, offset/2, (__le16 *)data, len/2);
ks8851_eeprom_release(ks); ks8851_eeprom_release(ks);
ks8851_unlock(ks, &flags);
return 0; return 0;
} }
...@@ -1262,6 +1299,7 @@ static int ks8851_phy_reg(int reg) ...@@ -1262,6 +1299,7 @@ static int ks8851_phy_reg(int reg)
static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg) static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg)
{ {
struct ks8851_net *ks = netdev_priv(dev); struct ks8851_net *ks = netdev_priv(dev);
unsigned long flags;
int ksreg; int ksreg;
int result; int result;
...@@ -1269,9 +1307,9 @@ static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg) ...@@ -1269,9 +1307,9 @@ static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg)
if (!ksreg) if (!ksreg)
return 0x0; /* no error return allowed, so use zero */ return 0x0; /* no error return allowed, so use zero */
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
result = ks8851_rdreg16(ks, ksreg); result = ks8851_rdreg16(ks, ksreg);
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
return result; return result;
} }
...@@ -1280,13 +1318,14 @@ static void ks8851_phy_write(struct net_device *dev, ...@@ -1280,13 +1318,14 @@ static void ks8851_phy_write(struct net_device *dev,
int phy, int reg, int value) int phy, int reg, int value)
{ {
struct ks8851_net *ks = netdev_priv(dev); struct ks8851_net *ks = netdev_priv(dev);
unsigned long flags;
int ksreg; int ksreg;
ksreg = ks8851_phy_reg(reg); ksreg = ks8851_phy_reg(reg);
if (ksreg) { if (ksreg) {
mutex_lock(&ks->lock); ks8851_lock(ks, &flags);
ks8851_wrreg16(ks, ksreg, value); ks8851_wrreg16(ks, ksreg, value);
mutex_unlock(&ks->lock); ks8851_unlock(ks, &flags);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment