Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 203635
b: refs/heads/master
c: 492c5d9
h: refs/heads/master
i:
  203633: 6745d5a
  203631: d698ba2
v: v3
  • Loading branch information
Catalin Marinas authored and David S. Miller committed Jul 19, 2010
1 parent da423e7 commit 5d80cf9
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 41 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 90e1795b9b18ce47e95cd26028a9cfd0f4cc35ba
refs/heads/master: 492c5d943d6a04b124ba3a719dc746dc36b14cfb
92 changes: 52 additions & 40 deletions trunk/drivers/net/smsc911x.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ struct smsc911x_data {
*/
spinlock_t mac_lock;

/* spinlock to ensure 16-bit accesses are serialised.
* unused with a 32-bit bus */
/* spinlock to ensure register accesses are serialised */
spinlock_t dev_lock;

struct phy_device *phy_dev;
Expand Down Expand Up @@ -118,107 +117,120 @@ struct smsc911x_data {
unsigned int hashlo;
};

/* The 16-bit access functions are significantly slower, due to the locking
* necessary. If your bus hardware can be configured to do this for you
* (in response to a single 32-bit operation from software), you should use
* the 32-bit access functions instead. */

static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
static inline u32 __smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
{
if (pdata->config.flags & SMSC911X_USE_32BIT)
return readl(pdata->ioaddr + reg);

if (pdata->config.flags & SMSC911X_USE_16BIT) {
u32 data;
unsigned long flags;

/* these two 16-bit reads must be performed consecutively, so
* must not be interrupted by our own ISR (which would start
* another read operation) */
spin_lock_irqsave(&pdata->dev_lock, flags);
data = ((readw(pdata->ioaddr + reg) & 0xFFFF) |
if (pdata->config.flags & SMSC911X_USE_16BIT)
return ((readw(pdata->ioaddr + reg) & 0xFFFF) |
((readw(pdata->ioaddr + reg + 2) & 0xFFFF) << 16));
spin_unlock_irqrestore(&pdata->dev_lock, flags);

return data;
}

BUG();
return 0;
}

static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
u32 val)
static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
{
u32 data;
unsigned long flags;

spin_lock_irqsave(&pdata->dev_lock, flags);
data = __smsc911x_reg_read(pdata, reg);
spin_unlock_irqrestore(&pdata->dev_lock, flags);

return data;
}

static inline void __smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
u32 val)
{
if (pdata->config.flags & SMSC911X_USE_32BIT) {
writel(val, pdata->ioaddr + reg);
return;
}

if (pdata->config.flags & SMSC911X_USE_16BIT) {
unsigned long flags;

/* these two 16-bit writes must be performed consecutively, so
* must not be interrupted by our own ISR (which would start
* another read operation) */
spin_lock_irqsave(&pdata->dev_lock, flags);
writew(val & 0xFFFF, pdata->ioaddr + reg);
writew((val >> 16) & 0xFFFF, pdata->ioaddr + reg + 2);
spin_unlock_irqrestore(&pdata->dev_lock, flags);
return;
}

BUG();
}

static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
u32 val)
{
unsigned long flags;

spin_lock_irqsave(&pdata->dev_lock, flags);
__smsc911x_reg_write(pdata, reg, val);
spin_unlock_irqrestore(&pdata->dev_lock, flags);
}

/* Writes a packet to the TX_DATA_FIFO */
static inline void
smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
unsigned int wordcount)
{
unsigned long flags;

spin_lock_irqsave(&pdata->dev_lock, flags);

if (pdata->config.flags & SMSC911X_SWAP_FIFO) {
while (wordcount--)
smsc911x_reg_write(pdata, TX_DATA_FIFO, swab32(*buf++));
return;
__smsc911x_reg_write(pdata, TX_DATA_FIFO,
swab32(*buf++));
goto out;
}

if (pdata->config.flags & SMSC911X_USE_32BIT) {
writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
return;
goto out;
}

if (pdata->config.flags & SMSC911X_USE_16BIT) {
while (wordcount--)
smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++);
return;
__smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++);
goto out;
}

BUG();
out:
spin_unlock_irqrestore(&pdata->dev_lock, flags);
}

/* Reads a packet out of the RX_DATA_FIFO */
static inline void
smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
unsigned int wordcount)
{
unsigned long flags;

spin_lock_irqsave(&pdata->dev_lock, flags);

if (pdata->config.flags & SMSC911X_SWAP_FIFO) {
while (wordcount--)
*buf++ = swab32(smsc911x_reg_read(pdata, RX_DATA_FIFO));
return;
*buf++ = swab32(__smsc911x_reg_read(pdata,
RX_DATA_FIFO));
goto out;
}

if (pdata->config.flags & SMSC911X_USE_32BIT) {
readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
return;
goto out;
}

if (pdata->config.flags & SMSC911X_USE_16BIT) {
while (wordcount--)
*buf++ = smsc911x_reg_read(pdata, RX_DATA_FIFO);
return;
*buf++ = __smsc911x_reg_read(pdata, RX_DATA_FIFO);
goto out;
}

BUG();
out:
spin_unlock_irqrestore(&pdata->dev_lock, flags);
}

/* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read
Expand Down

0 comments on commit 5d80cf9

Please sign in to comment.