summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@osdl.org>2003-09-03 22:42:03 -0700
committerPatrick Mochel <mochel@osdl.org>2003-09-03 22:42:03 -0700
commit8e4f908263846e259ddbee7024ad85d25ab786f7 (patch)
tree077df7e539942771b3fae2cc0fb4eb1bd4961003
parent0528415e4f6e55dfab981f5bdefe4a12379c9ecb (diff)
parent31412915d5d1de833892ac14d61db02ec8dce625 (diff)
Merge osdl.org:/home/mochel/src/kernel/linux-2.5-virgin
into osdl.org:/home/mochel/src/kernel/linux-2.5-power
-rw-r--r--Documentation/DocBook/scsidrivers.tmpl34
-rw-r--r--crypto/tcrypt.c1
-rw-r--r--drivers/atm/lanai.c427
-rw-r--r--drivers/ide/ide-cd.c1
-rw-r--r--drivers/ide/ide-default.c6
-rw-r--r--drivers/ide/ide-disk.c1
-rw-r--r--drivers/ide/ide-floppy.c1
-rw-r--r--drivers/ide/ide-tape.c1
-rw-r--r--drivers/ide/ide.c14
-rw-r--r--drivers/message/fusion/mptscsih.c7
-rw-r--r--drivers/net/3c509.c2
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/Space.c314
-rw-r--r--drivers/net/acenic.c10
-rwxr-xr-xdrivers/net/amd8111e.c2
-rw-r--r--drivers/net/appletalk/cops.c132
-rw-r--r--drivers/net/appletalk/ltpc.c251
-rw-r--r--drivers/net/b44.c2
-rw-r--r--drivers/net/bmac.c2
-rw-r--r--drivers/net/dgrs.c4
-rw-r--r--drivers/net/dl2k.c2
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--drivers/net/epic100.c2
-rw-r--r--drivers/net/fealnx.c2
-rw-r--r--drivers/net/hamachi.c2
-rw-r--r--drivers/net/ioc3-eth.c2
-rw-r--r--drivers/net/lasi_82596.c2
-rw-r--r--drivers/net/loopback.c72
-rw-r--r--drivers/net/lp486e.c2
-rw-r--r--drivers/net/natsemi.c6
-rw-r--r--drivers/net/pcnet32.c47
-rw-r--r--drivers/net/r8169.c4
-rw-r--r--drivers/net/rcpci45.c2
-rw-r--r--drivers/net/sb1000.c4
-rw-r--r--drivers/net/sis190.c15
-rw-r--r--drivers/net/sis900.c2
-rw-r--r--drivers/net/smc-mca.c33
-rw-r--r--drivers/net/starfire.c2
-rw-r--r--drivers/net/sundance.c2
-rw-r--r--drivers/net/sungem.c33
-rw-r--r--drivers/net/sunhme.c4
-rw-r--r--drivers/net/sunqe.c2
-rw-r--r--drivers/net/tg3.c2
-rw-r--r--drivers/net/tlan.c4
-rw-r--r--drivers/net/typhoon.c2
-rw-r--r--drivers/net/via-rhine.c2
-rw-r--r--drivers/net/wan/dlci.c129
-rw-r--r--drivers/net/wan/sbni.c57
-rw-r--r--drivers/net/wan/sdla.c160
-rw-r--r--drivers/net/yellowfin.c2
-rw-r--r--drivers/scsi/53c700.c2
-rw-r--r--drivers/scsi/AM53C974.c8
-rw-r--r--drivers/scsi/Kconfig97
-rw-r--r--drivers/scsi/Makefile3
-rw-r--r--drivers/scsi/NCR5380.c2
-rw-r--r--drivers/scsi/advansys.c12
-rw-r--r--drivers/scsi/arm/acornscsi.c6
-rw-r--r--drivers/scsi/arm/fas216.c4
-rw-r--r--drivers/scsi/cpqfcTSinit.c2
-rw-r--r--drivers/scsi/cpqfcTSworker.c2
-rw-r--r--drivers/scsi/dc395x.c1157
-rw-r--r--drivers/scsi/gdth.c12
-rw-r--r--drivers/scsi/gdth_proc.c4
-rw-r--r--drivers/scsi/ide-scsi.c1
-rw-r--r--drivers/scsi/imm.c1
-rw-r--r--drivers/scsi/ips.c10
-rw-r--r--drivers/scsi/ncr53c8xx.c13
-rw-r--r--drivers/scsi/osst.c2
-rw-r--r--drivers/scsi/qla1280.c6
-rw-r--r--drivers/scsi/scsi.c23
-rw-r--r--drivers/scsi/scsi_devinfo.c8
-rw-r--r--drivers/scsi/scsi_error.c2
-rw-r--r--drivers/scsi/scsi_ioctl.c28
-rw-r--r--drivers/scsi/scsi_lib.c2
-rw-r--r--drivers/scsi/scsi_logging.h40
-rw-r--r--drivers/scsi/scsi_priv.h26
-rw-r--r--drivers/scsi/scsi_proc.c106
-rw-r--r--drivers/scsi/scsi_scan.c18
-rw-r--r--drivers/scsi/scsi_sysctl.c53
-rw-r--r--drivers/scsi/sd.c41
-rw-r--r--drivers/scsi/sg.c38
-rw-r--r--drivers/scsi/sr.c4
-rw-r--r--drivers/scsi/sr_ioctl.c2
-rw-r--r--drivers/scsi/st.c2
-rw-r--r--drivers/scsi/sym53c8xx.c13
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_conf.h5
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h4
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.c4
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c451
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h34
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c47
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_misc.h19
-rw-r--r--drivers/scsi/sym53c8xx_defs.h15
-rw-r--r--drivers/usb/input/hiddev.c2
-rw-r--r--fs/proc/proc_misc.c14
-rw-r--r--include/asm-sparc/termios.h4
-rw-r--r--include/asm-sparc64/termios.h4
-rw-r--r--include/linux/fs.h4
-rw-r--r--include/linux/hiddev.h2
-rw-r--r--include/linux/ide.h1
-rw-r--r--include/linux/if_frad.h4
-rw-r--r--include/linux/initrd.h2
-rw-r--r--include/linux/netdevice.h4
-rw-r--r--include/linux/sysctl.h8
-rw-r--r--include/net/profile.h312
-rw-r--r--include/scsi/scsi_device.h2
-rw-r--r--include/scsi/scsi_request.h2
-rw-r--r--kernel/sysctl.c1
-rw-r--r--mm/mremap.c2
-rw-r--r--net/Kconfig1
-rw-r--r--net/atm/addr.c29
-rw-r--r--net/bluetooth/l2cap.c1
-rw-r--r--net/bluetooth/rfcomm/core.c2
-rw-r--r--net/bluetooth/rfcomm/sock.c1
-rw-r--r--net/bluetooth/sco.c1
-rw-r--r--net/core/Makefile1
-rw-r--r--net/core/dev.c82
-rw-r--r--net/core/link_watch.c1
-rw-r--r--net/core/netfilter.c4
-rw-r--r--net/core/profile.c294
-rw-r--r--net/decnet/dn_dev.c1
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c1
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c2
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c1
-rw-r--r--net/ipv4/udp.c75
-rw-r--r--net/ipv6/addrconf.c1
-rw-r--r--net/ipv6/af_inet6.c1
-rw-r--r--net/ipv6/ah6.c1
-rw-r--r--net/netlink/af_netlink.c4
-rw-r--r--net/rxrpc/sysctl.c1
-rw-r--r--net/sunrpc/stats.c1
135 files changed, 1832 insertions, 3199 deletions
diff --git a/Documentation/DocBook/scsidrivers.tmpl b/Documentation/DocBook/scsidrivers.tmpl
index 1dbafa7c2bd9..81e1561caf14 100644
--- a/Documentation/DocBook/scsidrivers.tmpl
+++ b/Documentation/DocBook/scsidrivers.tmpl
@@ -16,20 +16,40 @@
</affiliation>
</author>
</authorgroup>
- <pubdate>2002-04-27</pubdate>
+ <pubdate>2003-08-11</pubdate>
<copyright>
<year>2002</year>
+ <year>2003</year>
<holder>Douglas Gilbert</holder>
</copyright>
+
<legalnotice>
<para>
- Permission is granted to copy, distribute and/or modify this
- document under the terms of the GNU Free Documentation License,
- Version 1.1 or any later version published by the Free Software
- Foundation; with no Invariant Sections, with no Front-Cover Texts,
- and with no Back-Cover Texts. A copy of the license is included
- in the section entitled "GNU Free Documentation License".
+ This documentation is free software; you can redistribute
+ it and/or modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later
+ version.
+ </para>
+
+ <para>
+ This program is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied
+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+ </para>
+
+ <para>
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ MA 02111-1307 USA
+ </para>
+
+ <para>
+ For more details see the file COPYING in the source
+ distribution of Linux.
</para>
</legalnotice>
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index a66c2f086e25..338f48c1228f 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -15,7 +15,6 @@
*/
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/scatterlist.h>
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 1247846c538f..2fdb6f766e44 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -15,12 +15,6 @@
*
* Things not working yet:
*
- * o We're only set up to compile as a module currently. i.e.
- * you should put the source in drivers/atm/lanai.c and then
- * just do "make drivers/atm/lanai.o" from the main
- * source directory. This will produce a drivers/atm/lanai.o
- * file suitable for insmod'ing
- *
* o We don't support the Speedstream 3060 yet - this card has
* an on-board DSL modem chip by Alcatel and the driver will
* need some extra code added to handle it
@@ -245,9 +239,6 @@ struct lanai_vcc {
struct atm_vcc *atmvcc; /* atm_vcc who is transmitter */
int endptr; /* last endptr from service entry */
struct sk_buff_head backlog;
- struct sk_buff *inprogress; /* We're streaming this PDU */
- unsigned char *pptr; /* Where we are in above */
- int inprogleft; /* Bytes left to send "inprogress" */
void (*unqueue)(struct lanai_dev *, struct lanai_vcc *, int);
} tx;
};
@@ -268,8 +259,6 @@ struct lanai_dev_stats {
unsigned pcierr_m_target_abort;
unsigned pcierr_s_target_abort;
unsigned pcierr_master_parity;
- unsigned service_novcc_rx;
- unsigned service_novcc_tx;
unsigned service_notx;
unsigned service_norx;
unsigned service_rxnotaal5;
@@ -297,7 +286,7 @@ struct lanai_dev {
struct lanai_buffer aal0buf; /* AAL0 RX buffers */
u32 conf1, conf2; /* CONFIG[12] registers */
u32 status; /* STATUS register */
- spinlock_t txlock;
+ spinlock_t endtxlock;
spinlock_t servicelock;
struct atm_vcc *cbrvcc;
int number;
@@ -501,7 +490,6 @@ static inline void reg_write(const struct lanai_dev *lanai, u32 val,
RWDEBUG("W [0x%08X] 0x%02X < 0x%08X\n", (unsigned int) lanai->base,
(int) reg, val);
writel(val, reg_addr(lanai, reg));
- mdelay(1);
}
static inline void conf1_write(const struct lanai_dev *lanai)
@@ -537,63 +525,6 @@ static inline void reset_board(const struct lanai_dev *lanai)
udelay(5);
}
-/* -------------------- VCC LIST LOCK: */
-
-/*
- * The linux-atm code disables local IRQs while managing the list of
- * VCCs on a card. This is good, but it doesn't save us against
- * SMP. Unfortunately, fixing this will require changes in the
- * API which will have to wait a little bit. It's a hard race to
- * trigger accidentally, so it isn't TOO horrible so far.
- *
- * One possible solution would be to have an rwlock which is
- * always grabbed _irq-style on writing. This would automatically
- * be grabbed (for writing) by the higher layers on things that
- * would result in a change in the vcc list (_open, _close,
- * probably _change_qos) - thus it would also protect the
- * higher-level list of vccs on each device (atm_dev->vccs).
- * The driver would be responsible for grabbing it as a read_lock
- * anytime it wants to consult its table of vccs - for instance
- * when handling an incoming PDU. This also explains why we would
- * probably want the write_lock while in _change_qos - to prevent
- * handling of PDUs while possibly in an inconsistent state.
- * Also, _send would grab the lock for reading.
- *
- * One problem with this is that _open and _close could no longer
- * do anything that might provoke a schedule. First, it would
- * force us to use GFP_ATOMIC memory (which is bad), but also
- * some devices pretty much require scheduling due to long
- * delays (see lanai_close for an example). So in this case
- * we need a way to schedule without losing the spinlock.
- * The cleanest way to do this is probably have a way to mark a
- * VCC as "in progress" so that the interrupt handler can
- * still disregard any traffic for it while _open or _close
- * are sleeping on it. Then it will need to be _open and
- * _close's job to relinquish the write_lock. Thus, the
- * lock could be dropped around the times that scheduling
- * might occur. Perhaps the _READY flag can be used for
- * this purpose.
- *
- * One short note about this "upper layer grabs, driver
- * relinquishes" write lock - since this needs to be
- * an _irq lock we're going to have problem saving
- * and restoring flags (_irqsave/_irqrestore). This
- * shouldn't be a problem, however - we must just
- * require that those syscalls are never called with
- * interrupts disabled so we can use the non-flags-saving
- * versions.
- *
- * Anyway, all of the above is vaporware currently - fixing
- * this right will require changes in the API and all of
- * the drivers - this will wait until 2.5.x most likely.
- * The following NOP macros are just here to mark where
- * the locks will be needed in the future.
- */
-#define vcclist_read_lock() do {} while (0)
-#define vcclist_read_unlock() do {} while (0)
-#define vcclist_write_lock() do {} while (0)
-#define vcclist_write_unlock() do {} while (0)
-
/* -------------------- CARD SRAM UTILITIES: */
/* The SRAM is mapped into normal PCI memory space - the only catch is
@@ -851,36 +782,39 @@ static void lanai_shutdown_tx_vci(struct lanai_dev *lanai,
if (lvcc->vbase == 0) /* We were never bound to a VCI */
return;
/* 15.2.1 - wait for queue to drain */
- spin_lock_irqsave(&lanai->txlock, flags);
- if (lvcc->tx.inprogress != NULL) {
- lanai_free_skb(lvcc->tx.atmvcc, lvcc->tx.inprogress);
- lvcc->tx.inprogress = NULL;
- }
while ((skb = skb_dequeue(&lvcc->tx.backlog)) != NULL)
lanai_free_skb(lvcc->tx.atmvcc, skb);
+ read_lock_irqsave(&vcc_sklist_lock, flags);
__clear_bit(lvcc->vci, lanai->backlog_vccs);
- spin_unlock_irqrestore(&lanai->txlock, flags);
- timeout = jiffies + ((lanai_buf_size(&lvcc->tx.buf) * HZ) >> 17);
+ read_unlock_irqrestore(&vcc_sklist_lock, flags);
+ /*
+ * We need to wait for the VCC to drain but don't wait forever. We
+ * give each 1K of buffer size 1/128th of a second to clear out.
+ * TODO: maybe disable CBR if we're about to timeout?
+ */
+ timeout = jiffies +
+ (((lanai_buf_size(&lvcc->tx.buf) / 1024) * HZ) >> 7);
write = TXWRITEPTR_GET_PTR(cardvcc_read(lvcc, vcc_txwriteptr));
- goto start;
- while (time_before_eq(jiffies, timeout)) {
- schedule_timeout(HZ / 25);
- start:
+ for (;;) {
read = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr));
if (read == write && /* Is TX buffer empty? */
(lvcc->tx.atmvcc->qos.txtp.traffic_class != ATM_CBR ||
(cardvcc_read(lvcc, vcc_txcbr_next) &
TXCBR_NEXT_BOZO) == 0))
- goto done;
+ break;
if (read != lastread) { /* Has there been any progress? */
lastread = read;
timeout += HZ / 10;
}
+ if (unlikely(time_after(jiffies, timeout))) {
+ printk(KERN_ERR DEV_LABEL "(itf %d): Timed out on "
+ "backlog closing vci %d\n",
+ lvcc->tx.atmvcc->dev->number, lvcc->vci);
+ DPRINTK("read, write = %d, %d\n", read, write);
+ break;
+ }
+ schedule_timeout(HZ / 25);
}
- printk(KERN_ERR DEV_LABEL "(itf %d): Timed out on backlog closing "
- "vci %d\n", lvcc->tx.atmvcc->dev->number, lvcc->vci);
- DPRINTK("read, write = %d, %d\n", read, write);
- done:
/* 15.2.2 - clear out all tx registers */
cardvcc_write(lvcc, 0, vcc_txreadptr);
cardvcc_write(lvcc, 0, vcc_txwriteptr);
@@ -1226,8 +1160,7 @@ static inline int vcc_tx_space(const struct lanai_vcc *lvcc, int endptr)
/* test if VCC is currently backlogged */
static inline int vcc_is_backlogged(/*const*/ struct lanai_vcc *lvcc)
{
- return lvcc->tx.inprogress != NULL ||
- !skb_queue_empty(&lvcc->tx.backlog);
+ return !skb_queue_empty(&lvcc->tx.backlog);
}
/* Bit fields in the segmentation buffer descriptor */
@@ -1264,11 +1197,11 @@ static inline void vcc_tx_add_aal5_descriptor(struct lanai_vcc *lvcc,
}
/* Add 32-bit AAL5 trailer and leave room for its CRC */
-static inline void vcc_tx_add_aal5trailer(struct lanai_vcc *lvcc,
+static inline void vcc_tx_add_aal5_trailer(struct lanai_vcc *lvcc,
int len, int cpi, int uu)
{
APRINTK((((unsigned long) lvcc->tx.buf.ptr) & 15) == 8,
- "vcc_tx_add_aal5_descriptor: bad ptr=%p\n", lvcc->tx.buf.ptr);
+ "vcc_tx_add_aal5_trailer: bad ptr=%p\n", lvcc->tx.buf.ptr);
lvcc->tx.buf.ptr += 2;
lvcc->tx.buf.ptr[-2] = cpu_to_be32((uu << 24) | (cpi << 16) | len);
if (lvcc->tx.buf.ptr >= lvcc->tx.buf.end)
@@ -1311,7 +1244,7 @@ static inline void vcc_tx_memzero(struct lanai_vcc *lvcc, int n)
}
/* Update "butt" register to specify new WritePtr */
-static inline void lanai_endtx(const struct lanai_dev *lanai,
+static inline void lanai_endtx(struct lanai_dev *lanai,
const struct lanai_vcc *lvcc)
{
int i, ptr = ((unsigned char *) lvcc->tx.buf.ptr) -
@@ -1320,6 +1253,14 @@ static inline void lanai_endtx(const struct lanai_dev *lanai,
"lanai_endtx: bad ptr (%d), vci=%d, start,ptr,end=%p,%p,%p\n",
ptr, lvcc->vci, lvcc->tx.buf.start, lvcc->tx.buf.ptr,
lvcc->tx.buf.end);
+
+ /*
+ * Since the "butt register" is a shared resounce on the card we
+ * serialize all accesses to it through this spinlock. This is
+ * mostly just paranoia sicne the register is rarely "busy" anyway
+ * but is needed for correctness.
+ */
+ spin_lock(&lanai->endtxlock);
/*
* We need to check if the "butt busy" bit is set before
* updating the butt register. In theory this should
@@ -1334,131 +1275,86 @@ static inline void lanai_endtx(const struct lanai_dev *lanai,
}
udelay(5);
}
+ /*
+ * Before we tall the card to start work we need to be sure 100% of
+ * the info in the service buffer has been written before we tell
+ * the card about it
+ */
+ wmb();
reg_write(lanai, (ptr << 12) | lvcc->vci, Butt_Reg);
+ spin_unlock(&lanai->endtxlock);
+}
+
+/*
+ * Add one AAL5 PDU to lvcc's transmit buffer. Caller garauntees there's
+ * space available. "pdusize" is the number of bytes the PDU will take
+ */
+static void lanai_send_one_aal5(struct lanai_dev *lanai,
+ struct lanai_vcc *lvcc, struct sk_buff *skb, int pdusize)
+{
+ int pad;
+ APRINTK(pdusize == aal5_size(skb->len),
+ "lanai_send_one_aal5: wrong size packet (%d != %d)\n",
+ pdusize, aal5_size(skb->len));
+ vcc_tx_add_aal5_descriptor(lvcc, 0, pdusize);
+ pad = pdusize - skb->len - 8;
+ APRINTK(pad >= 0, "pad is negative (%d)\n", pad);
+ APRINTK(pad < 48, "pad is too big (%d)\n", pad);
+ vcc_tx_memcpy(lvcc, skb->data, skb->len);
+ vcc_tx_memzero(lvcc, pad);
+ vcc_tx_add_aal5_trailer(lvcc, skb->len, 0, 0);
+ lanai_endtx(lanai, lvcc);
+ lanai_free_skb(lvcc->tx.atmvcc, skb);
+ atomic_inc(&lvcc->tx.atmvcc->stats->tx);
}
/* Try to fill the buffer - don't call unless there is backlog */
static void vcc_tx_unqueue_aal5(struct lanai_dev *lanai,
struct lanai_vcc *lvcc, int endptr)
{
- int pad, n;
+ int n;
struct sk_buff *skb;
int space = vcc_tx_space(lvcc, endptr);
APRINTK(vcc_is_backlogged(lvcc),
"vcc_tx_unqueue() called with empty backlog (vci=%d)\n",
lvcc->vci);
- if (space < 64)
- return; /* No space for even 1 cell+descriptor */
- if (lvcc->tx.inprogress != NULL) {
- APRINTK((lvcc->tx.inprogleft % 48) == 0,
- "vcc_tx_unqueue_aal5: bad progleft=%d\n",
- lvcc->tx.inprogleft);
- if (lvcc->tx.inprogleft + 16 > space) { /* Can't send all? */
- n = aal5_spacefor(space - 16); /* Bytes to send */
- vcc_tx_add_aal5_descriptor(lvcc,
- DESCRIPTOR_AAL5_STREAM, n);
- pad = lvcc->tx.pptr + n - lvcc->tx.inprogress->tail;
- if (pad < 0)
- pad = 0;
- vcc_tx_memcpy(lvcc, lvcc->tx.pptr, n - pad);
- vcc_tx_memzero(lvcc, pad);
- lvcc->tx.pptr += n;
- lvcc->tx.inprogleft -= n;
- goto end; /* Buffer is now full */
- }
- /* OK, there's at least space for all of "inprogress" skb */
- vcc_tx_add_aal5_descriptor(lvcc, 0,
- lvcc->tx.inprogleft);
- pad = lvcc->tx.pptr + lvcc->tx.inprogleft -
- lvcc->tx.inprogress->tail;
- if (pad >= lvcc->tx.inprogleft) { /* Nothing but pad left */
- APRINTK(lvcc->tx.inprogleft == 48,
- "vcc_tx_unqueue_aal5: bad pure-pad=%d\n",
- lvcc->tx.inprogleft);
- pad = 48;
- } else
- vcc_tx_memcpy(lvcc, lvcc->tx.pptr,
- lvcc->tx.inprogleft - pad);
- vcc_tx_memzero(lvcc, pad - 8);
- vcc_tx_add_aal5trailer(lvcc, lvcc->tx.inprogress->len, 0, 0);
- lanai_free_skb(lvcc->tx.atmvcc, lvcc->tx.inprogress);
- lvcc->tx.inprogress = NULL;
- space -= lvcc->tx.inprogleft + 16;
- atomic_inc(&lvcc->tx.atmvcc->stats->tx);
- }
while (space >= 64) {
- if ((skb = skb_dequeue(&lvcc->tx.backlog)) == NULL)
- break;
+ skb = skb_dequeue(&lvcc->tx.backlog);
+ if (skb == NULL)
+ goto no_backlog;
n = aal5_size(skb->len);
- if (n + 16 > space) { /* Can only send part */
- int m = aal5_spacefor(space - 16); /* Bytes to send */
- vcc_tx_add_aal5_descriptor(lvcc,
- DESCRIPTOR_AAL5_STREAM, m);
- lvcc->tx.pptr = skb->data + m;
- pad = lvcc->tx.pptr - skb->tail;
- if (pad < 0)
- pad = 0;
- vcc_tx_memcpy(lvcc, skb->data, m - pad);
- vcc_tx_memzero(lvcc, pad);
- lvcc->tx.inprogleft = n - m;
- lvcc->tx.inprogress = skb;
- goto end;
+ if (n + 16 > space) {
+ /* No room for this packet - put it back on queue */
+ skb_queue_head(&lvcc->tx.backlog, skb);
+ return;
}
- vcc_tx_add_aal5_descriptor(lvcc, 0, n);
- pad = n - skb->len - 8;
- vcc_tx_memcpy(lvcc, skb->data, skb->len);
- vcc_tx_memzero(lvcc, pad);
- lanai_free_skb(lvcc->tx.atmvcc, skb);
- vcc_tx_add_aal5trailer(lvcc, skb->len, 0, 0);
+ lanai_send_one_aal5(lanai, lvcc, skb, n);
space -= n + 16;
- atomic_inc(&lvcc->tx.atmvcc->stats->tx);
}
- if (skb_queue_empty(&lvcc->tx.backlog))
+ if (!vcc_is_backlogged(lvcc)) {
+ no_backlog:
__clear_bit(lvcc->vci, lanai->backlog_vccs);
- end:
- lanai_endtx(lanai, lvcc);
+ }
}
/* Given an skb that we want to transmit either send it now or queue */
static void vcc_tx_aal5(struct lanai_dev *lanai, struct lanai_vcc *lvcc,
struct sk_buff *skb)
{
- int space, n, pad;
+ int space, n;
if (vcc_is_backlogged(lvcc)) /* Already backlogged */
goto queue_it;
- space = vcc_tx_space(lvcc, TXREADPTR_GET_PTR(cardvcc_read(lvcc,
- vcc_txreadptr)));
- if (space < 64) { /* No space at all */
- __set_bit(lvcc->vci, lanai->backlog_vccs);
- goto queue_it;
- }
- if (space >= 16 + (n = aal5_size(skb->len))) {
- /* We can send the whole thing now */
- vcc_tx_add_aal5_descriptor(lvcc, 0, n);
- pad = n - skb->len;
- vcc_tx_memcpy(lvcc, skb->data, skb->len);
- vcc_tx_memzero(lvcc, pad - 8);
- vcc_tx_add_aal5trailer(lvcc, skb->len, 0, 0);
- lanai_free_skb(lvcc->tx.atmvcc, skb);
- atomic_inc(&lvcc->tx.atmvcc->stats->tx);
- } else { /* Space for only part of skb */
- int bytes = aal5_spacefor(space - 16); /* Bytes to send */
- vcc_tx_add_aal5_descriptor(lvcc,
- DESCRIPTOR_AAL5_STREAM, bytes);
- pad = bytes - skb->len;
- if (pad < 0)
- pad = 0;
- vcc_tx_memcpy(lvcc, skb->data, bytes - pad);
- vcc_tx_memzero(lvcc, pad);
- lvcc->tx.inprogress = skb;
- lvcc->tx.inprogleft = n - bytes;
- lvcc->tx.pptr = skb->data + bytes;
+ space = vcc_tx_space(lvcc,
+ TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr)));
+ n = aal5_size(skb->len);
+ APRINTK(n + 16 >= 64, "vcc_tx_aal5: n too small (%d)\n", n);
+ if (space < n + 16) { /* No space for this PDU */
__set_bit(lvcc->vci, lanai->backlog_vccs);
+ queue_it:
+ skb_queue_tail(&lvcc->tx.backlog, skb);
+ return;
}
- lanai_endtx(lanai, lvcc);
- return;
- queue_it:
- skb_queue_tail(&lvcc->tx.backlog, skb);
+ lanai_send_one_aal5(lanai, lvcc, skb, n);
}
static void vcc_tx_unqueue_aal0(struct lanai_dev *lanai,
@@ -1476,28 +1372,6 @@ static void vcc_tx_aal0(struct lanai_dev *lanai, struct lanai_vcc *lvcc,
lanai_free_skb(lvcc->tx.atmvcc, skb);
}
-/* Try to undequeue 1 backlogged vcc */
-static void iter_dequeue(struct lanai_dev *lanai, vci_t vci)
-{
- struct lanai_vcc *lvcc = lanai->vccs[vci];
- int endptr;
- if (lvcc == NULL || !vcc_is_backlogged(lvcc)) {
- __clear_bit(vci, lanai->backlog_vccs);
- return;
- }
- endptr = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr));
- lvcc->tx.unqueue(lanai, lvcc, endptr);
-}
-
-/* Try a dequeue on all backlogged connections */
-static inline void vcc_tx_dequeue_all(struct lanai_dev *lanai)
-{
- unsigned long flags;
- spin_lock_irqsave(&lanai->txlock, flags);
- vci_bitfield_iterate(lanai, lanai->backlog_vccs, iter_dequeue);
- spin_unlock_irqrestore(&lanai->txlock, flags);
-}
-
/* -------------------- VCC RX BUFFER UTILITIES: */
/* unlike the _tx_ cousins, this doesn't update ptr */
@@ -1510,6 +1384,8 @@ static inline void vcc_rx_memcpy(unsigned char *dest,
m = 0;
memcpy(dest, lvcc->rx.buf.ptr, n - m);
memcpy(dest + n - m, lvcc->rx.buf.start, m);
+ /* Make sure that these copies don't get reordered */
+ barrier();
}
/* Receive AAL5 data on a VCC with a particular endptr */
@@ -1527,6 +1403,11 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr)
/* Recover the second-to-last word to get true pdu length */
if ((x = &end[-2]) < lvcc->rx.buf.start)
x = &lvcc->rx.buf.end[-2];
+ /*
+ * Before we actually read from the buffer, make sure the memory
+ * changes have arrived
+ */
+ rmb();
size = be32_to_cpup(x) & 0xffff;
if (unlikely(n != aal5_size(size))) {
/* Make sure size matches padding */
@@ -1542,9 +1423,9 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr)
goto out;
}
skb_put(skb, size);
+ vcc_rx_memcpy(skb->data, lvcc, size);
ATM_SKB(skb)->vcc = lvcc->rx.atmvcc;
do_gettimeofday(&skb->stamp);
- vcc_rx_memcpy(skb->data, lvcc, size);
lvcc->rx.atmvcc->push(lvcc->rx.atmvcc, skb);
atomic_inc(&lvcc->rx.atmvcc->stats->rx);
out:
@@ -1555,7 +1436,7 @@ static void vcc_rx_aal5(struct lanai_vcc *lvcc, int endptr)
static void vcc_rx_aal0(struct lanai_dev *lanai)
{
printk(KERN_INFO DEV_LABEL ": vcc_rx_aal0: not implemented\n");
- /* Remember to get vcclist_read_lock while looking up VC */
+ /* Remember to get read_lock(&vcc_sklist_lock) while looking up VC */
/* Remember to increment lvcc->rx.atmvcc->stats->rx */
}
@@ -1606,7 +1487,6 @@ static inline struct lanai_vcc *new_lanai_vcc(void)
memset(&lvcc->stats, 0, sizeof lvcc->stats);
lvcc->rx.buf.start = lvcc->tx.buf.start = NULL;
skb_queue_head_init(&lvcc->tx.backlog);
- lvcc->tx.inprogress = NULL;
#ifdef DEBUG
lvcc->tx.unqueue = NULL;
lvcc->vci = -1;
@@ -1617,14 +1497,14 @@ static inline struct lanai_vcc *new_lanai_vcc(void)
static int lanai_get_sized_buffer(struct lanai_dev *lanai,
struct lanai_buffer *buf, int max_sdu, int multiplier,
- int min, const char *name)
+ const char *name)
{
int size;
if (unlikely(max_sdu < 1))
max_sdu = 1;
max_sdu = aal5_size(max_sdu);
size = (max_sdu + 16) * multiplier + 16;
- lanai_buf_allocate(buf, size, min, lanai->pci);
+ lanai_buf_allocate(buf, size, max_sdu + 32, lanai->pci);
if (unlikely(buf->start == NULL))
return -ENOMEM;
if (unlikely(lanai_buf_size(buf) < size))
@@ -1640,8 +1520,7 @@ static inline int lanai_setup_rx_vci_aal5(struct lanai_dev *lanai,
struct lanai_vcc *lvcc, const struct atm_qos *qos)
{
return lanai_get_sized_buffer(lanai, &lvcc->rx.buf,
- qos->rxtp.max_sdu, AAL5_RX_MULTIPLIER, qos->rxtp.max_sdu + 32,
- "RX");
+ qos->rxtp.max_sdu, AAL5_RX_MULTIPLIER, "RX");
}
/* Setup a TX buffer for a currently unbound AAL5 vci */
@@ -1659,7 +1538,7 @@ static int lanai_setup_tx_vci(struct lanai_dev *lanai, struct lanai_vcc *lvcc,
multiplier = AAL5_TX_MULTIPLIER;
}
return lanai_get_sized_buffer(lanai, &lvcc->tx.buf, max_sdu,
- multiplier, 80, "TX");
+ multiplier, "TX");
}
static inline void host_vcc_bind(struct lanai_dev *lanai,
@@ -1759,21 +1638,21 @@ static int handle_service(struct lanai_dev *lanai, u32 s)
{
vci_t vci = SERVICE_GET_VCI(s);
struct lanai_vcc *lvcc;
- vcclist_read_lock();
+ read_lock(&vcc_sklist_lock);
lvcc = lanai->vccs[vci];
if (unlikely(lvcc == NULL)) {
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
DPRINTK("(itf %d) got service entry 0x%X for nonexistent "
"vcc %d\n", lanai->number, (unsigned int) s, vci);
if (s & SERVICE_TX)
- lanai->stats.service_novcc_tx++;
+ lanai->stats.service_notx++;
else
- lanai->stats.service_novcc_rx++;
+ lanai->stats.service_norx++;
return 0;
}
if (s & SERVICE_TX) { /* segmentation interrupt */
if (unlikely(lvcc->tx.atmvcc == NULL)) {
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
DPRINTK("(itf %d) got service entry 0x%X for non-TX "
"vcc %d\n", lanai->number, (unsigned int) s, vci);
lanai->stats.service_notx++;
@@ -1781,18 +1660,18 @@ static int handle_service(struct lanai_dev *lanai, u32 s)
}
__set_bit(vci, lanai->transmit_ready);
lvcc->tx.endptr = SERVICE_GET_END(s);
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
return 1;
}
if (unlikely(lvcc->rx.atmvcc == NULL)) {
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
DPRINTK("(itf %d) got service entry 0x%X for non-RX "
"vcc %d\n", lanai->number, (unsigned int) s, vci);
lanai->stats.service_norx++;
return 0;
}
if (unlikely(lvcc->rx.atmvcc->qos.aal != ATM_AAL5)) {
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
DPRINTK("(itf %d) got RX service entry 0x%X for non-AAL5 "
"vcc %d\n", lanai->number, (unsigned int) s, vci);
lanai->stats.service_rxnotaal5++;
@@ -1801,12 +1680,12 @@ static int handle_service(struct lanai_dev *lanai, u32 s)
}
if (likely(!(s & (SERVICE_TRASH | SERVICE_STREAM | SERVICE_CRCERR)))) {
vcc_rx_aal5(lvcc, SERVICE_GET_END(s));
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
return 0;
}
if (s & SERVICE_TRASH) {
int bytes;
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
DPRINTK("got trashed rx pdu on vci %d\n", vci);
atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
lvcc->stats.x.aal5.service_trash++;
@@ -1819,7 +1698,7 @@ static int handle_service(struct lanai_dev *lanai, u32 s)
return 0;
}
if (s & SERVICE_STREAM) {
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
atomic_inc(&lvcc->rx.atmvcc->stats->rx_err);
lvcc->stats.x.aal5.service_stream++;
printk(KERN_ERR DEV_LABEL "(itf %d): Got AAL5 stream "
@@ -1832,7 +1711,7 @@ static int handle_service(struct lanai_dev *lanai, u32 s)
lvcc->stats.x.aal5.service_rxcrc++;
lvcc->rx.buf.ptr = &lvcc->rx.buf.start[SERVICE_GET_END(s) * 4];
cardvcc_write(lvcc, SERVICE_GET_END(s), vcc_rxreadptr);
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
return 0;
}
@@ -1840,9 +1719,8 @@ static int handle_service(struct lanai_dev *lanai, u32 s)
static void iter_transmit(struct lanai_dev *lanai, vci_t vci)
{
struct lanai_vcc *lvcc = lanai->vccs[vci];
- if (!vcc_is_backlogged(lvcc))
- return;
- lvcc->tx.unqueue(lanai, lvcc, lvcc->tx.endptr);
+ if (vcc_is_backlogged(lvcc))
+ lvcc->tx.unqueue(lanai, lvcc, lvcc->tx.endptr);
}
/* Run service queue -- called from interrupt context or with
@@ -1862,13 +1740,11 @@ static void run_service(struct lanai_dev *lanai)
}
reg_write(lanai, wreg, ServRead_Reg);
if (ntx != 0) {
- spin_lock(&lanai->txlock);
- vcclist_read_lock();
+ read_lock(&vcc_sklist_lock);
vci_bitfield_iterate(lanai, lanai->transmit_ready,
iter_transmit);
CLEAR_BITMAP(&lanai->transmit_ready, NUM_VCI);
- vcclist_read_unlock();
- spin_unlock(&lanai->txlock);
+ read_unlock(&vcc_sklist_lock);
}
}
@@ -1885,22 +1761,47 @@ static void get_statistics(struct lanai_dev *lanai)
/* -------------------- POLLING TIMER: */
+#ifndef DEBUG_RW
+/* Try to undequeue 1 backlogged vcc */
+static void iter_dequeue(struct lanai_dev *lanai, vci_t vci)
+{
+ struct lanai_vcc *lvcc = lanai->vccs[vci];
+ int endptr;
+ if (lvcc == NULL || lvcc->tx.atmvcc == NULL ||
+ !vcc_is_backlogged(lvcc)) {
+ __clear_bit(vci, lanai->backlog_vccs);
+ return;
+ }
+ endptr = TXREADPTR_GET_PTR(cardvcc_read(lvcc, vcc_txreadptr));
+ lvcc->tx.unqueue(lanai, lvcc, endptr);
+}
+#endif /* !DEBUG_RW */
+
static void lanai_timed_poll(unsigned long arg)
{
-#ifndef DEBUG_RW
struct lanai_dev *lanai = (struct lanai_dev *) arg;
+#ifndef DEBUG_RW
unsigned long flags;
#ifdef USE_POWERDOWN
if (lanai->conf1 & CONFIG1_POWERDOWN)
return;
-#endif
- spin_lock_irqsave(&lanai->servicelock, flags);
- run_service(lanai);
- spin_unlock_irqrestore(&lanai->servicelock, flags);
- vcc_tx_dequeue_all(lanai);
+#endif /* USE_POWERDOWN */
+ local_irq_save(flags);
+ /* If we can grab the spinlock, check if any services need to be run */
+ if (spin_trylock(&lanai->servicelock)) {
+ run_service(lanai);
+ spin_unlock(&lanai->servicelock);
+ }
+ /* ...and see if any backlogged VCs can make progress */
+ /* unfortunately linux has no read_trylock() currently */
+ read_lock(&vcc_sklist_lock);
+ vci_bitfield_iterate(lanai, lanai->backlog_vccs, iter_dequeue);
+ read_unlock(&vcc_sklist_lock);
+ local_irq_restore(flags);
+
get_statistics(lanai);
+#endif /* !DEBUG_RW */
mod_timer(&lanai->timer, jiffies + LANAI_POLL_PERIOD);
-#endif /* DEBUG_RW */
}
static inline void lanai_timed_poll_start(struct lanai_dev *lanai)
@@ -1914,7 +1815,7 @@ static inline void lanai_timed_poll_start(struct lanai_dev *lanai)
static inline void lanai_timed_poll_stop(struct lanai_dev *lanai)
{
- del_timer(&lanai->timer);
+ del_timer_sync(&lanai->timer);
}
/* -------------------- INTERRUPT SERVICE: */
@@ -2265,13 +2166,13 @@ static int __init lanai_dev_open(struct atm_dev *atmdev)
#endif
lanai->cbrvcc = NULL;
memset(&lanai->stats, 0, sizeof lanai->stats);
- spin_lock_init(&lanai->txlock);
+ spin_lock_init(&lanai->endtxlock);
spin_lock_init(&lanai->servicelock);
atmdev->ci_range.vpi_bits = 0;
atmdev->ci_range.vci_bits = 0;
while (1 << atmdev->ci_range.vci_bits < lanai->num_vci)
atmdev->ci_range.vci_bits++;
- atmdev->link_rate = ((25600000 / 8 - 8000) / 54);
+ atmdev->link_rate = ATM_25_PCR;
/* 3.2: PCI initialization */
if ((result = lanai_pci_start(lanai)) != 0)
@@ -2342,6 +2243,7 @@ static int __init lanai_dev_open(struct atm_dev *atmdev)
goto error_vcctable;
}
MOD_INC_USE_COUNT; /* At this point we can't fail */
+ mb(); /* Make sure that all that made it */
intr_enable(lanai, INT_ALL & ~(INT_PING | INT_WAKE));
/* 3.11: initialize loop mode (i.e. turn looping off) */
lanai->conf1 = (lanai->conf1 & ~CONFIG1_MASK_LOOPMODE) |
@@ -2466,16 +2368,11 @@ static int lanai_open(struct atm_vcc *atmvcc, short vpi, int vci)
atmvcc->vpi = vpi;
atmvcc->vci = vci;
set_bit(ATM_VF_ADDR, &atmvcc->flags);
- lvcc = lanai->vccs[vci];
if (atmvcc->qos.aal != ATM_AAL0 && atmvcc->qos.aal != ATM_AAL5)
return -EINVAL;
-#if 0
- DPRINTK(DEV_LABEL "(itf %d): open %d.%d flags=0x%lX\n",
- lanai->number, (int) vpi, vci, (unsigned long) atmvcc->flags);
-#else
DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n", lanai->number,
(int) vpi, vci);
-#endif
+ lvcc = lanai->vccs[vci];
if (lvcc == NULL) {
lvcc = new_lanai_vcc();
if (unlikely(lvcc == NULL))
@@ -2517,6 +2414,11 @@ static int lanai_open(struct atm_vcc *atmvcc, short vpi, int vci)
}
}
host_vcc_bind(lanai, lvcc, vci);
+ /*
+ * Make sure everything made it to RAM before we tell the card about
+ * the VCC
+ */
+ wmb();
if (atmvcc == lvcc->rx.atmvcc)
host_vcc_start_rx(lvcc);
if (atmvcc == lvcc->tx.atmvcc) {
@@ -2549,9 +2451,6 @@ static int lanai_ioctl(struct atm_dev *atmdev, unsigned int cmd, void *arg)
run_service(lanai);
spin_unlock_irqrestore(&lanai->servicelock, flags);
return 0; }
- case 2200001:
- vcc_tx_dequeue_all(lanai);
- return 0;
case 2200002:
get_statistics(lanai);
return 0;
@@ -2644,18 +2543,18 @@ static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb)
ATM_SKB(skb)->vcc = atmvcc;
switch (atmvcc->qos.aal) {
case ATM_AAL5:
- spin_lock_irqsave(&lanai->txlock, flags);
+ read_lock_irqsave(&vcc_sklist_lock, flags);
vcc_tx_aal5(lanai, lvcc, skb);
- spin_unlock_irqrestore(&lanai->txlock, flags);
+ read_unlock_irqrestore(&vcc_sklist_lock, flags);
return 0;
case ATM_AAL0:
if (unlikely(skb->len != ATM_CELL_SIZE-1))
goto einval;
/* NOTE - this next line is technically invalid - we haven't unshared skb */
cpu_to_be32s((u32 *) skb->data);
- spin_lock_irqsave(&lanai->txlock, flags);
+ read_lock_irqsave(&vcc_sklist_lock, flags);
vcc_tx_aal0(lanai, lvcc, skb);
- spin_unlock_irqrestore(&lanai->txlock, flags);
+ read_unlock_irqrestore(&vcc_sklist_lock, flags);
return 0;
}
DPRINTK("lanai_send: bad aal=%d on vci=%d\n", (int) atmvcc->qos.aal,
@@ -2725,10 +2624,6 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page)
"master_parity=%u\n", lanai->stats.pcierr_s_target_abort,
lanai->stats.pcierr_master_parity);
if (left-- == 0)
- return sprintf(page, "service list errors: no_vcc_rx=%u, "
- "no_vcc_tx=%u,\n", lanai->stats.service_novcc_rx,
- lanai->stats.service_novcc_tx);
- if (left-- == 0)
return sprintf(page, " no_tx=%u, "
"no_rx=%u, bad_rx_aal=%u\n", lanai->stats.service_norx,
lanai->stats.service_notx,
@@ -2737,7 +2632,7 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page)
return sprintf(page, "resets: dma=%u, card=%u\n",
lanai->stats.dma_reenable, lanai->stats.card_reset);
/* At this point, "left" should be the VCI we're looking for */
- vcclist_read_lock();
+ read_lock(&vcc_sklist_lock);
for (; ; left++) {
if (left >= NUM_VCI) {
left = 0;
@@ -2773,7 +2668,7 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page)
page[left++] = '\n';
page[left] = '\0';
out:
- vcclist_read_unlock();
+ read_unlock(&vcc_sklist_lock);
return left;
}
#endif /* CONFIG_PROC_FS */
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 578476e1e931..fd5874b891db 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -3318,7 +3318,6 @@ static ide_driver_t ide_cdrom_driver = {
.version = IDECD_VERSION,
.media = ide_cdrom,
.busy = 0,
- .supports_dma = 1,
.supports_dsc_overlap = 1,
.cleanup = ide_cdrom_cleanup,
.do_request = ide_do_rw_cdrom,
diff --git a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c
index 40ecc4de0c05..0c251121a740 100644
--- a/drivers/ide/ide-default.c
+++ b/drivers/ide/ide-default.c
@@ -40,18 +40,12 @@ static int idedefault_attach(ide_drive_t *drive);
/*
* IDE subdriver functions, registered with ide.c
- *
- * idedefault *must* support DMA because it will be
- * attached before the other drivers are loaded and
- * we don't want to lose the DMA status at probe
- * time.
*/
ide_driver_t idedefault_driver = {
.name = "ide-default",
.version = IDEDEFAULT_VERSION,
.attach = idedefault_attach,
- .supports_dma = 1,
.drives = LIST_HEAD_INIT(idedefault_driver.drives)
};
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 1217e840ac02..39693bcc7d0f 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1716,7 +1716,6 @@ static ide_driver_t idedisk_driver = {
.version = IDEDISK_VERSION,
.media = ide_disk,
.busy = 0,
- .supports_dma = 1,
.supports_dsc_overlap = 0,
.cleanup = idedisk_cleanup,
.flushcache = do_idedisk_flushcache,
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 112dc8b8676d..4a2a7273b8b4 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1854,7 +1854,6 @@ static ide_driver_t idefloppy_driver = {
.version = IDEFLOPPY_VERSION,
.media = ide_floppy,
.busy = 0,
- .supports_dma = 1,
.supports_dsc_overlap = 0,
.cleanup = idefloppy_cleanup,
.do_request = idefloppy_do_request,
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index e2bdaa457727..6c8c067df5a7 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -6316,7 +6316,6 @@ static ide_driver_t idetape_driver = {
.version = IDETAPE_VERSION,
.media = ide_tape,
.busy = 1,
- .supports_dma = 1,
.supports_dsc_overlap = 1,
.cleanup = idetape_cleanup,
.do_request = idetape_do_request,
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 8ff22ad3f648..b6b7c97bf090 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1359,8 +1359,6 @@ static int set_io_32bit(ide_drive_t *drive, int arg)
static int set_using_dma (ide_drive_t *drive, int arg)
{
- if (!DRIVER(drive)->supports_dma)
- return -EPERM;
if (!drive->id || !(drive->id->capability & 1))
return -EPERM;
if (HWIF(drive)->ide_dma_check == NULL)
@@ -2406,6 +2404,13 @@ static ide_startstop_t default_abort (ide_drive_t *drive, const char *msg)
return ide_abort(drive, msg);
}
+static ide_startstop_t default_start_power_step(ide_drive_t *drive,
+ struct request *rq)
+{
+ rq->pm->pm_step = ide_pm_state_completed;
+ return ide_stopped;
+}
+
static void setup_driver_defaults (ide_driver_t *d)
{
if (d->cleanup == NULL) d->cleanup = default_cleanup;
@@ -2420,6 +2425,8 @@ static void setup_driver_defaults (ide_driver_t *d)
if (d->capacity == NULL) d->capacity = default_capacity;
if (d->special == NULL) d->special = default_special;
if (d->attach == NULL) d->attach = default_attach;
+ if (d->start_power_step == NULL)
+ d->start_power_step = default_start_power_step;
}
int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version)
@@ -2443,9 +2450,6 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio
if ((drive->autotune == IDE_TUNE_DEFAULT) ||
(drive->autotune == IDE_TUNE_AUTO)) {
/* DMA timings and setup moved to ide-probe.c */
- if (!driver->supports_dma && HWIF(drive)->ide_dma_off_quietly)
-// HWIF(drive)->ide_dma_off_quietly(drive);
- HWIF(drive)->ide_dma_off(drive);
drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap);
drive->nice1 = 1;
}
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index a5a449a4a7d9..680507243d4a 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -475,6 +475,8 @@ mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
(struct scatterlist *) SCpnt->request_buffer,
SCpnt->use_sg,
scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+ if (sges_left == 0)
+ return FAILED;
} else if (SCpnt->request_bufflen) {
dma_addr_t buf_dma_addr;
scPrivate *my_priv;
@@ -3328,9 +3330,8 @@ mptscsih_slave_configure(Scsi_Device *device)
device, device->id, device->lun, device->channel));
dsprintk((KERN_INFO "sdtr %d wdtr %d ppr %d inq length=%d\n",
device->sdtr, device->wdtr, device->ppr, device->inquiry_len));
- dsprintk(("tagged %d queue %d simple %d ordered %d\n",
- device->tagged_supported, device->tagged_queue,
- device->simple_tags, device->ordered_tags));
+ dsprintk(("tagged %d simple %d ordered %d\n",
+ device->tagged_supported, device->simple_tags, device->ordered_tags));
/* set target parameters, queue depths, set dv flags ? */
if (hd && (hd->Targets != NULL)) {
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index df5f96439afa..74fd4100332b 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -604,7 +604,7 @@ out1:
pnp_device_detach(idev);
#endif
out:
- kfree(dev);
+ free_netdev(dev);
return err;
}
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 4e3eabe1e5ea..572de917454d 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1468,7 +1468,7 @@ free_ring:
free_region:
if (vp->must_free_region)
release_region(ioaddr, vci->io_size);
- kfree (dev);
+ free_netdev(dev);
printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval);
out:
return retval;
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index a49241c1ae23..fc3c04c6c7bc 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1768,7 +1768,7 @@ err_out_mwi:
err_out_disable:
pci_disable_device(pdev);
err_out_free:
- kfree(dev);
+ free_netdev(dev);
return rc;
}
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 46777c8dcf18..1963e60de0b2 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -32,14 +32,13 @@
*/
#include <linux/config.h>
#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/trdevice.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/netlink.h>
#include <linux/divert.h>
-#define NEXT_DEV NULL
-
-
/* A unified ethernet device probe. This is the easiest way to have every
ethernet adaptor have the name "eth[0123...]".
*/
@@ -98,6 +97,15 @@ extern int macsonic_probe(struct net_device *dev);
extern int mac8390_probe(struct net_device *dev);
extern int mac89x0_probe(struct net_device *dev);
extern int mc32_probe(struct net_device *dev);
+#ifdef CONFIG_SDLA
+extern struct net_device *sdla_init(void);
+#endif
+#ifdef CONFIG_COPS
+extern struct net_device *cops_probe(int unit);
+#endif
+#ifdef CONFIG_LTPC
+extern struct net_device *ltpc_probe(void);
+#endif
/* Detachable devices ("pocket adaptors") */
extern int de620_probe(struct net_device *);
@@ -106,7 +114,7 @@ extern int de620_probe(struct net_device *);
extern int iph5526_probe(struct net_device *dev);
/* SBNI adapters */
-extern int sbni_probe(struct net_device *);
+extern int sbni_probe(void);
struct devprobe
{
@@ -352,124 +360,43 @@ static struct devprobe mips_probes[] __initdata = {
* per bus interface. This drives the legacy devices only for now.
*/
-static int __init ethif_probe(struct net_device *dev)
+static int __init ethif_probe(void)
{
- unsigned long base_addr = dev->base_addr;
+ struct net_device *dev;
+ int err = -ENODEV;
+
+ dev = alloc_etherdev(0);
+ if (!dev)
+ return -ENOMEM;
+
+ netdev_boot_setup_check(dev);
/*
* Backwards compatibility - historically an I/O base of 1 was
* used to indicate not to probe for this ethN interface
*/
- if (base_addr == 1)
- return 1; /* ENXIO */
+ if (dev->base_addr == 1) {
+ free_netdev(dev);
+ return -ENXIO;
+ }
/*
* The arch specific probes are 1st so that any on-board ethernet
* will be probed before other ISA/EISA/MCA/PCI bus cards.
*/
- if (probe_list(dev, m68k_probes) == 0)
- return 0;
- if (probe_list(dev, mips_probes) == 0)
- return 0;
- if (probe_list(dev, eisa_probes) == 0)
- return 0;
- if (probe_list(dev, mca_probes) == 0)
- return 0;
- if (probe_list(dev, isa_probes) == 0)
- return 0;
- if (probe_list(dev, parport_probes) == 0)
- return 0;
- return -ENODEV;
-}
-
-#ifdef CONFIG_SDLA
-extern int sdla_init(struct net_device *);
-static struct net_device sdla0_dev = {
- .name = "sdla0",
- .next = NEXT_DEV,
- .init = sdla_init,
-};
-#undef NEXT_DEV
-#define NEXT_DEV (&sdla0_dev)
-#endif
-
-#if defined(CONFIG_LTPC)
-extern int ltpc_probe(struct net_device *);
-static struct net_device dev_ltpc = {
- .name = "lt0",
- .next = NEXT_DEV,
- .init = ltpc_probe
-};
-#undef NEXT_DEV
-#define NEXT_DEV (&dev_ltpc)
-#endif /* LTPC */
-
-#if defined(CONFIG_COPS)
-extern int cops_probe(struct net_device *);
-static struct net_device cops2_dev = {
- .name = "lt2",
- .next = NEXT_DEV,
- .init = cops_probe,
-};
-static struct net_device cops1_dev = {
- .name = "lt1",
- .next = &cops2_dev,
- .init = cops_probe,
-};
-static struct net_device cops0_dev = {
- .name = "lt0",
- .next = &cops1_dev,
- .init = cops_probe,
-};
-#undef NEXT_DEV
-#define NEXT_DEV (&cops0_dev)
-#endif /* COPS */
-
-static struct net_device eth7_dev = {
- .name = "eth%d",
- .next = NEXT_DEV,
- .init = ethif_probe,
-};
-static struct net_device eth6_dev = {
- .name = "eth%d",
- .next = &eth7_dev,
- .init = ethif_probe,
-};
-static struct net_device eth5_dev = {
- .name = "eth%d",
- .next = &eth6_dev,
- .init = ethif_probe,
-};
-static struct net_device eth4_dev = {
- .name = "eth%d",
- .next = &eth5_dev,
- .init = ethif_probe,
-};
-static struct net_device eth3_dev = {
- .name = "eth%d",
- .next = &eth4_dev,
- .init = ethif_probe,
-};
-static struct net_device eth2_dev = {
- .name = "eth%d",
- .next = &eth3_dev,
- .init = ethif_probe,
-};
-static struct net_device eth1_dev = {
- .name = "eth%d",
- .next = &eth2_dev,
- .init = ethif_probe,
-};
-static struct net_device eth0_dev = {
- .name = "eth%d",
- .next = &eth1_dev,
- .init = ethif_probe,
-};
-
-#undef NEXT_DEV
-#define NEXT_DEV (&eth0_dev)
-
+ if (probe_list(dev, m68k_probes) == 0 ||
+ probe_list(dev, mips_probes) == 0 ||
+ probe_list(dev, eisa_probes) == 0 ||
+ probe_list(dev, mca_probes) == 0 ||
+ probe_list(dev, isa_probes) == 0 ||
+ probe_list(dev, parport_probes) == 0)
+ err = register_netdev(dev);
+
+ if (err)
+ free_netdev(dev);
+ return err;
+}
#ifdef CONFIG_TR
/* Token-ring device probe */
@@ -478,129 +405,82 @@ extern int sk_isa_probe(struct net_device *);
extern int proteon_probe(struct net_device *);
extern int smctr_probe(struct net_device *);
-static int
-trif_probe(struct net_device *dev)
+static __init int trif_probe(void)
{
- if (1
+ struct net_device *dev;
+ int err = -ENODEV;
+
+ dev = alloc_trdev(0);
+ if (!dev)
+ return -ENOMEM;
+
+ netdev_boot_setup_check(dev);
+ if (
#ifdef CONFIG_IBMTR
- && ibmtr_probe(dev)
+ ibmtr_probe(dev) == 0 ||
#endif
#ifdef CONFIG_SKISA
- && sk_isa_probe(dev)
+ sk_isa_probe(dev) == 0 ||
#endif
#ifdef CONFIG_PROTEON
- && proteon_probe(dev)
+ proteon_probe(dev) == 0 ||
#endif
#ifdef CONFIG_SMCTR
- && smctr_probe(dev)
+ smctr_probe(dev) == 0 ||
#endif
- && 1 ) {
- return 1; /* -ENODEV or -EAGAIN would be more accurate. */
- }
- return 0;
-}
-static struct net_device tr7_dev = {
- .name = "tr%d",
- .next = NEXT_DEV,
- .init = trif_probe,
-};
-static struct net_device tr6_dev = {
- .name = "tr%d",
- .next = &tr7_dev,
- .init = trif_probe,
-};
-static struct net_device tr5_dev = {
- .name = "tr%d",
- .next = &tr6_dev,
- .init = trif_probe,
-};
-static struct net_device tr4_dev = {
- .name = "tr%d",
- .next = &tr5_dev,
- .init = trif_probe,
-};
-static struct net_device tr3_dev = {
- .name = "tr%d",
- .next = &tr4_dev,
- .init = trif_probe,
-};
-static struct net_device tr2_dev = {
- .name = "tr%d",
- .next = &tr3_dev,
- .init = trif_probe,
-};
-static struct net_device tr1_dev = {
- .name = "tr%d",
- .next = &tr2_dev,
- .init = trif_probe,
-};
-static struct net_device tr0_dev = {
- .name = "tr%d",
- .next = &tr1_dev,
- .init = trif_probe,
-};
-#undef NEXT_DEV
-#define NEXT_DEV (&tr0_dev)
+ 0 )
+ err = register_netdev(dev);
+
+ if (err)
+ free_netdev(dev);
+ return err;
-#endif
-
-#ifdef CONFIG_SBNI
-static struct net_device sbni7_dev = {
- .name = "sbni7",
- .next = NEXT_DEV,
- .init = sbni_probe,
-};
-static struct net_device sbni6_dev = {
- .name = "sbni6",
- .next = &sbni7_dev,
- .init = sbni_probe,
-};
-static struct net_device sbni5_dev = {
- .name = "sbni5",
- .next = &sbni6_dev,
- .init = sbni_probe,
-};
-static struct net_device sbni4_dev = {
- .name = "sbni4",
- .next = &sbni5_dev,
- .init = sbni_probe,
-};
-static struct net_device sbni3_dev = {
- .name = "sbni3",
- .next = &sbni4_dev,
- .init = sbni_probe,
-};
-static struct net_device sbni2_dev = {
- .name = "sbni2",
- .next = &sbni3_dev,
- .init = sbni_probe,
-};
-static struct net_device sbni1_dev = {
- .name = "sbni1",
- .next = &sbni2_dev,
- .init = sbni_probe,
-};
-static struct net_device sbni0_dev = {
- .name = "sbni0",
- .next = &sbni1_dev,
- .init = sbni_probe,
-};
+}
+#endif
-#undef NEXT_DEV
-#define NEXT_DEV (&sbni0_dev)
-#endif
/*
* The loopback device is global so it can be directly referenced
* by the network code. Also, it must be first on device list.
*/
+extern int loopback_init(void);
-extern int loopback_init(struct net_device *dev);
-struct net_device loopback_dev = {
- .name = "lo",
- .next = NEXT_DEV,
- .init = loopback_init
-};
+/* Statically configured drivers -- order matters here. */
+void __init probe_old_netdevs(void)
+{
+ int num;
+
+ if (loopback_init()) {
+ printk(KERN_ERR "Network loopback device setup failed\n");
+ }
+
+
+#ifdef CONFIG_SBNI
+ for (num = 0; num < 8; ++num)
+ if (sbni_probe())
+ break;
+#endif
+#ifdef CONFIG_TR
+ for (num = 0; num < 8; ++num)
+ if (trif_probe())
+ break;
+#endif
+ for (num = 0; num < 8; ++num)
+ if (ethif_probe())
+ break;
+#ifdef CONFIG_COPS
+ cops_probe(0);
+ cops_probe(1);
+ cops_probe(2);
+#endif
+#ifdef CONFIG_LTPC
+ ltpc_probe();
+#endif
+#ifdef CONFIG_SDLA
+ sdla_init();
+#endif
+
+}
/*
* The @dev_base list is protected by @dev_base_lock and the rtln
@@ -621,6 +501,6 @@ struct net_device loopback_dev = {
* unregister_netdevice(), which must be called with the rtnl
* semaphore held.
*/
-struct net_device *dev_base = &loopback_dev;
+struct net_device *dev_base;
rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index d6a4fdcec957..3350a70c2103 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -685,7 +685,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG)
}
if (pci_enable_device(pdev)) {
- kfree(dev);
+ free_netdev(dev);
continue;
}
@@ -733,7 +733,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG)
if (register_netdev(dev)) {
printk(KERN_ERR "acenic: device registration failed\n");
- kfree(dev);
+ free_netdev(dev);
continue;
}
@@ -793,7 +793,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG)
printk(KERN_ERR "%s: Driver compiled without Tigon I"
" support - NIC disabled\n", dev->name);
ace_init_cleanup(dev);
- kfree(dev);
+ free_netdev(dev);
continue;
}
#endif
@@ -803,7 +803,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG)
* ace_allocate_descriptors() calls
* ace_init_cleanup() on error.
*/
- kfree(dev);
+ free_netdev(dev);
continue;
}
@@ -820,7 +820,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG)
/*
* ace_init() calls ace_init_cleanup() on error.
*/
- kfree(dev);
+ free_netdev(dev);
continue;
}
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 19464a83fdfb..bc9e1bfc7220 100755
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -1927,7 +1927,7 @@ err_iounmap:
iounmap((void *) lp->mmio);
err_free_dev:
- kfree(dev);
+ free_netdev(dev);
err_free_reg:
pci_release_regions(pdev);
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index cb8dac24f286..579cf0d2ee5b 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -92,12 +92,8 @@ static int board_type = DAYNA; /* Module exported */
static int board_type = TANGENT;
#endif
-#ifdef MODULE
static int io = 0x240; /* Default IO for Dayna */
static int irq = 5; /* Default IRQ */
-#else
-static int io; /* Default IO for Dayna */
-#endif
/*
* COPS Autoprobe information.
@@ -146,7 +142,7 @@ static int io; /* Default IO for Dayna */
* Zero terminated list of IO ports to probe.
*/
-static unsigned int cops_portlist[] = {
+static unsigned int ports[] = {
0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260,
0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360,
0
@@ -184,7 +180,6 @@ struct cops_local
};
/* Index to functions, as function prototypes. */
-extern int cops_probe (struct net_device *dev);
static int cops_probe1 (struct net_device *dev, int ioaddr);
static int cops_irq (int ioaddr, int board);
@@ -208,6 +203,12 @@ static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static int cops_close (struct net_device *dev);
static struct net_device_stats *cops_get_stats (struct net_device *dev);
+static void cleanup_card(struct net_device *dev)
+{
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, COPS_IO_EXTENT);
+}
/*
* Check for a network adaptor of this type, and return '0' iff one exists.
@@ -215,31 +216,54 @@ static struct net_device_stats *cops_get_stats (struct net_device *dev);
* If dev->base_addr in [1..0x1ff], always return failure.
* otherwise go with what we pass in.
*/
-int __init cops_probe(struct net_device *dev)
+struct net_device * __init cops_probe(int unit)
{
- int i;
- int base_addr = dev->base_addr;
+ struct net_device *dev;
+ unsigned *port;
+ int base_addr;
+ int err = 0;
+
+ dev = alloc_netdev(sizeof(struct cops_local), "lt%d", ltalk_setup);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ if (unit >= 0) {
+ sprintf(dev->name, "lt%d", unit);
+ netdev_boot_setup_check(dev);
+ irq = dev->irq;
+ base_addr = dev->base_addr;
+ } else {
+ base_addr = dev->base_addr = io;
+ }
SET_MODULE_OWNER(dev);
- if(base_addr == 0 && io)
- base_addr=io;
-
- if(base_addr > 0x1ff) /* Check a single specified location. */
- return cops_probe1(dev, base_addr);
- else if(base_addr != 0) /* Don't probe at all. */
- return -ENXIO;
-
- /* FIXME Does this really work for cards which generate irq?
- * It's definitely N.G. for polled Tangent. sh
- * Dayna cards don't autoprobe well at all, but if your card is
- * at IRQ 5 & IO 0x240 we find it every time. ;) JS
- */
- for(i=0; cops_portlist[i]; i++)
- if(cops_probe1(dev, cops_portlist[i]) == 0)
- return 0;
-
- return -ENODEV;
+ if (base_addr > 0x1ff) { /* Check a single specified location. */
+ err = cops_probe1(dev, base_addr);
+ } else if (base_addr != 0) { /* Don't probe at all. */
+ err = -ENXIO;
+ } else {
+ /* FIXME Does this really work for cards which generate irq?
+ * It's definitely N.G. for polled Tangent. sh
+ * Dayna cards don't autoprobe well at all, but if your card is
+ * at IRQ 5 & IO 0x240 we find it every time. ;) JS
+ */
+ for (port = ports; *port && cops_probe1(dev, *port) < 0; port++)
+ ;
+ if (!*port)
+ err = -ENODEV;
+ }
+ if (err)
+ goto out;
+ err = register_netdev(dev);
+ if (err)
+ goto out1;
+ return dev;
+out1:
+ cleanup_card(dev);
+out:
+ kfree(dev);
+ return ERR_PTR(err);
}
/*
@@ -268,16 +292,15 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
* interrupts are typically not reported by the boards, and we must
* used AutoIRQ to find them.
*/
+ dev->irq = irq;
switch (dev->irq)
{
case 0:
/* COPS AutoIRQ routine */
dev->irq = cops_irq(ioaddr, board);
- if(!dev->irq) {
- retval = -EINVAL; /* No IRQ found on this port */
- goto err_out;
- }
-
+ if (dev->irq)
+ break;
+ /* No IRQ found on this port, fallthrough */
case 1:
retval = -EINVAL;
goto err_out;
@@ -302,22 +325,13 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
}
/* Reserve any actual interrupt. */
- if(dev->irq) {
+ if (dev->irq) {
retval = request_irq(dev->irq, &cops_interrupt, 0, dev->name, dev);
if (retval)
goto err_out;
}
- dev->base_addr = ioaddr;
-
- /* Initialize the private device structure. */
- dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL);
- if(dev->priv == NULL) {
- if (dev->irq)
- free_irq(dev->irq, dev);
- retval = -ENOMEM;
- goto err_out;
- }
+ dev->base_addr = ioaddr;
lp = (struct cops_local *)dev->priv;
memset(lp, 0, sizeof(struct cops_local));
@@ -326,9 +340,6 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
/* Copy local board variable to lp struct. */
lp->board = board;
- /* Fill in the fields of the device structure with LocalTalk values. */
- ltalk_setup(dev);
-
dev->hard_start_xmit = cops_send_packet;
dev->tx_timeout = cops_timeout;
dev->watchdog_timeo = HZ * 2;
@@ -1013,7 +1024,7 @@ static struct net_device_stats *cops_get_stats(struct net_device *dev)
}
#ifdef MODULE
-static struct net_device cops0_dev = { .init = cops_probe };
+static struct net_device *cops_dev;
MODULE_LICENSE("GPL");
MODULE_PARM(io, "i");
@@ -1022,33 +1033,20 @@ MODULE_PARM(board_type, "i");
int init_module(void)
{
- int result, err;
-
- if(io == 0)
+ if (io == 0)
printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
cardname);
-
- /* Copy the parameters from insmod into the device structure. */
- cops0_dev.base_addr = io;
- cops0_dev.irq = irq;
-
- err=dev_alloc_name(&cops0_dev, "lt%d");
- if(err < 0)
- return err;
-
- if((result = register_netdev(&cops0_dev)) != 0)
- return result;
-
+ cops_dev = cops_probe(-1);
+ if (IS_ERR(cops_dev))
+ return PTR_ERR(cops_dev);
return 0;
}
void cleanup_module(void)
{
- unregister_netdev(&cops0_dev);
- kfree(cops0_dev.priv);
- if(cops0_dev.irq)
- free_irq(cops0_dev.irq, &cops0_dev);
- release_region(cops0_dev.base_addr, COPS_IO_EXTENT);
+ unregister_netdev(cops_dev);
+ cleanup_card(cops_dev);
+ free_netdev(cops_dev);
}
#endif /* MODULE */
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index ddbd4f765b12..1b10bc14867c 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -879,34 +879,6 @@ static int ltpc_hard_header (struct sk_buff *skb, struct net_device *dev,
return 0;
}
-static int ltpc_init(struct net_device *dev)
-{
- /* Initialize the device structure. */
-
- /* Fill in the fields of the device structure with ethernet-generic values. */
- ltalk_setup(dev);
- dev->hard_start_xmit = ltpc_xmit;
- dev->hard_header = ltpc_hard_header;
-
- dev->priv = kmalloc(sizeof(struct ltpc_private), GFP_KERNEL);
- if(!dev->priv)
- {
- printk(KERN_INFO "%s: could not allocate statistics buffer\n", dev->name);
- return -ENOMEM;
- }
-
- memset(dev->priv, 0, sizeof(struct ltpc_private));
- dev->get_stats = ltpc_get_stats;
-
- /* add the ltpc-specific things */
- dev->do_ioctl = &ltpc_ioctl;
-
- dev->set_multicast_list = &set_multicast_list;
- dev->mc_list = NULL;
-
- return 0;
-}
-
static int ltpc_poll_counter;
static void ltpc_poll(unsigned long l)
@@ -983,35 +955,40 @@ static struct net_device_stats *ltpc_get_stats(struct net_device *dev)
/* initialization stuff */
-static int __init ltpc_probe_dma(int base)
+static int __init ltpc_probe_dma(int base, int dma)
{
- int dma = 0;
+ int want = (dma == 3) ? 2 : (dma == 1) ? 1 : 3;
unsigned long timeout;
unsigned long f;
- if (!request_dma(1,"ltpc")) {
- f=claim_dma_lock();
- disable_dma(1);
- clear_dma_ff(1);
- set_dma_mode(1,DMA_MODE_WRITE);
- set_dma_addr(1,virt_to_bus(ltdmabuf));
- set_dma_count(1,sizeof(struct lt_mem));
- enable_dma(1);
- release_dma_lock(f);
- dma|=1;
+ if (want & 1) {
+ if (request_dma(1,"ltpc")) {
+ want &= ~1;
+ } else {
+ f=claim_dma_lock();
+ disable_dma(1);
+ clear_dma_ff(1);
+ set_dma_mode(1,DMA_MODE_WRITE);
+ set_dma_addr(1,virt_to_bus(ltdmabuf));
+ set_dma_count(1,sizeof(struct lt_mem));
+ enable_dma(1);
+ release_dma_lock(f);
+ }
}
- if (!request_dma(3,"ltpc")) {
- f=claim_dma_lock();
- disable_dma(3);
- clear_dma_ff(3);
- set_dma_mode(3,DMA_MODE_WRITE);
- set_dma_addr(3,virt_to_bus(ltdmabuf));
- set_dma_count(3,sizeof(struct lt_mem));
- enable_dma(3);
- release_dma_lock(f);
- dma|=2;
+ if (want & 2) {
+ if (request_dma(3,"ltpc")) {
+ want &= ~2;
+ } else {
+ f=claim_dma_lock();
+ disable_dma(3);
+ clear_dma_ff(3);
+ set_dma_mode(3,DMA_MODE_WRITE);
+ set_dma_addr(3,virt_to_bus(ltdmabuf));
+ set_dma_count(3,sizeof(struct lt_mem));
+ enable_dma(3);
+ release_dma_lock(f);
+ }
}
-
/* set up request */
/* FIXME -- do timings better! */
@@ -1037,65 +1014,62 @@ static int __init ltpc_probe_dma(int base)
/* release the other dma channel (if we opened both of them) */
- if ( (dma&0x2) && (get_dma_residue(3)==sizeof(struct lt_mem)) ){
- dma&=1;
+ if ((want & 2) && (get_dma_residue(3)==sizeof(struct lt_mem))) {
+ want &= ~2;
free_dma(3);
}
-
- if ( (dma&0x1) && (get_dma_residue(1)==sizeof(struct lt_mem)) ){
- dma&=0x2;
+
+ if ((want & 1) && (get_dma_residue(1)==sizeof(struct lt_mem))) {
+ want &= ~1;
free_dma(1);
}
- /* fix up dma number */
- dma|=1;
+ if (!want)
+ return 0;
- return dma;
+ return (want & 2) ? 3 : 1;
}
-int __init ltpc_probe(struct net_device *dev)
+struct net_device * __init ltpc_probe(void)
{
- int err;
+ struct net_device *dev;
+ int err = -ENOMEM;
int x=0,y=0;
int autoirq;
unsigned long f;
- int portfound=0;
unsigned long timeout;
+ dev = alloc_netdev(sizeof(struct ltpc_private), "lt%d", ltalk_setup);
+ if (!dev)
+ goto out;
+
SET_MODULE_OWNER(dev);
/* probe for the I/O port address */
+
if (io != 0x240 && request_region(0x220,8,"ltpc")) {
x = inb_p(0x220+6);
if ( (x!=0xff) && (x>=0xf0) ) {
io = 0x220;
- portfound=1;
- }
- else {
- release_region(0x220,8);
+ goto got_port;
}
+ release_region(0x220,8);
}
-
if (io != 0x220 && request_region(0x240,8,"ltpc")) {
y = inb_p(0x240+6);
if ( (y!=0xff) && (y>=0xf0) ){
io = 0x240;
- portfound=1;
- }
- else {
- release_region(0x240,8);
+ goto got_port;
}
+ release_region(0x240,8);
}
- if(io && !portfound && request_region(io,8,"ltpc")){
- portfound = 1;
- }
- if(!portfound) {
- /* give up in despair */
- printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y);
- return -1;
- }
+ /* give up in despair */
+ printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y);
+ err = -ENODEV;
+ goto out1;
+ got_port:
/* probe for the IRQ line */
if (irq < 2) {
unsigned long irq_mask;
@@ -1111,22 +1085,21 @@ int __init ltpc_probe(struct net_device *dev)
if (autoirq == 0) {
printk(KERN_ERR "ltpc: probe at %#x failed to detect IRQ line.\n", io);
- }
- else {
+ } else {
irq = autoirq;
}
}
/* allocate a DMA buffer */
ltdmabuf = (unsigned char *) dma_mem_alloc(1000);
-
- if (ltdmabuf) ltdmacbuf = &ltdmabuf[800];
-
if (!ltdmabuf) {
printk(KERN_ERR "ltpc: mem alloc failed\n");
- return -1;
+ err = -ENOMEM;
+ goto out2;
}
+ ltdmacbuf = &ltdmabuf[800];
+
if(debug & DEBUG_VERBOSE) {
printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf);
}
@@ -1154,25 +1127,29 @@ int __init ltpc_probe(struct net_device *dev)
already been specified */
/* well, 0 is a legal DMA channel, but the LTPC card doesn't
use it... */
- if (dma == 0) {
- dma = ltpc_probe_dma(io);
- if (!dma) { /* no dma channel */
- printk(KERN_ERR "No DMA channel found on ltpc card.\n");
- return -1;
- }
+ dma = ltpc_probe_dma(io, dma);
+ if (!dma) { /* no dma channel */
+ printk(KERN_ERR "No DMA channel found on ltpc card.\n");
+ err = -ENODEV;
+ goto out3;
}
/* print out friendly message */
-
if(irq)
printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma);
else
printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma);
- /* seems more logical to do this *after* probing the card... */
- err = ltpc_init(dev);
- if (err) return err;
+ /* Fill in the fields of the device structure with ethernet-generic values. */
+ dev->hard_start_xmit = ltpc_xmit;
+ dev->hard_header = ltpc_hard_header;
+ dev->get_stats = ltpc_get_stats;
+ /* add the ltpc-specific things */
+ dev->do_ioctl = &ltpc_ioctl;
+
+ dev->set_multicast_list = &set_multicast_list;
+ dev->mc_list = NULL;
dev->base_addr = io;
dev->irq = irq;
dev->dma = dma;
@@ -1212,6 +1189,7 @@ int __init ltpc_probe(struct net_device *dev)
} else {
if( irq )
printk(KERN_ERR "ltpc: IRQ already in use, using polled mode.\n");
+ dev->irq = 0;
/* polled mode -- 20 times per second */
/* this is really, really slow... should it poll more often? */
init_timer(&ltpc_timer);
@@ -1221,8 +1199,23 @@ int __init ltpc_probe(struct net_device *dev)
ltpc_timer.expires = jiffies + HZ/20;
add_timer(&ltpc_timer);
}
+ err = register_netdev(dev);
+ if (err)
+ goto out4;
return 0;
+out4:
+ del_timer_sync(&ltpc_timer);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+out3:
+ free_pages((unsigned long)ltdmabuf, get_order(1000));
+out2:
+ release_region(io, 8);
+out1:
+ kfree(dev);
+out:
+ return ERR_PTR(err);
}
#ifndef MODULE
@@ -1259,7 +1252,7 @@ static int __init ltpc_setup(char *str)
__setup("ltpc=", ltpc_setup);
#endif /* MODULE */
-static struct net_device dev_ltpc;
+static struct net_device *dev_ltpc;
#ifdef MODULE
@@ -1272,79 +1265,47 @@ MODULE_PARM(dma, "i");
int __init init_module(void)
{
- int err, result;
-
if(io == 0)
printk(KERN_NOTICE
"ltpc: Autoprobing is not recommended for modules\n");
- /* Find a name for this unit */
- dev_ltpc.init = ltpc_probe;
- err=dev_alloc_name(&dev_ltpc,"lt%d");
-
- if(err<0)
- return err;
-
- if ((result = register_netdev(&dev_ltpc)) != 0) {
- printk(KERN_DEBUG "could not register Localtalk-PC device\n");
- return result;
- } else {
- if(debug & DEBUG_VERBOSE) printk("0 from register_netdev\n");
- return 0;
- }
+ dev_ltpc = ltpc_probe();
+ if (IS_ERR(dev_ltpc))
+ return PTR_ERR(dev_ltpc);
+ return 0;
}
#endif
static void __exit ltpc_cleanup(void)
{
- unsigned long timeout;
+
+ if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n");
+ unregister_netdev(dev_ltpc);
ltpc_timer.data = 0; /* signal the poll routine that we're done */
+ del_timer_sync(&ltpc_timer);
+
if(debug & DEBUG_VERBOSE) printk("freeing irq\n");
- if(dev_ltpc.irq) {
- free_irq(dev_ltpc.irq,&dev_ltpc);
- dev_ltpc.irq = 0;
- }
-
- if(del_timer(&ltpc_timer))
- {
- /* either the poll was never started, or a poll is in process */
- if(debug & DEBUG_VERBOSE) printk("waiting\n");
- /* if it's in process, wait a bit for it to finish */
- timeout = jiffies+HZ;
- add_timer(&ltpc_timer);
- while(del_timer(&ltpc_timer) && time_after(timeout, jiffies))
- {
- add_timer(&ltpc_timer);
- schedule();
- }
- }
+ if (dev_ltpc->irq)
+ free_irq(dev_ltpc->irq, dev_ltpc);
if(debug & DEBUG_VERBOSE) printk("freeing dma\n");
- if(dev_ltpc.dma) {
- free_dma(dev_ltpc.dma);
- dev_ltpc.dma = 0;
- }
+ if (dev_ltpc->dma)
+ free_dma(dev_ltpc->dma);
if(debug & DEBUG_VERBOSE) printk("freeing ioaddr\n");
- if(dev_ltpc.base_addr) {
- release_region(dev_ltpc.base_addr,8);
- dev_ltpc.base_addr = 0;
- }
+ if (dev_ltpc->base_addr)
+ release_region(dev_ltpc->base_addr,8);
+
+ free_netdev(dev_ltpc);
if(debug & DEBUG_VERBOSE) printk("free_pages\n");
free_pages( (unsigned long) ltdmabuf, get_order(1000));
- ltdmabuf=NULL;
- ltdmacbuf=NULL;
-
- if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n");
-
- unregister_netdev(&dev_ltpc);
if(debug & DEBUG_VERBOSE) printk("returning from cleanup_module\n");
}
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index b759af47913d..ef10d16fd679 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1834,7 +1834,7 @@ err_out_iounmap:
iounmap((void *) bp->regs);
err_out_free_dev:
- kfree(dev);
+ free_netdev(dev);
err_out_free_res:
pci_release_regions(pdev);
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index ed7874f4fe4e..27bc8ed937cf 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -1462,7 +1462,7 @@ out2:
release_OF_resource(bp->node, 0);
out1:
pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0);
- kfree(dev);
+ free_netdev(dev);
}
static int bmac_open(struct net_device *dev)
diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c
index 00ddd19e0fd2..d28d864cbaa5 100644
--- a/drivers/net/dgrs.c
+++ b/drivers/net/dgrs.c
@@ -1275,7 +1275,7 @@ dgrs_found_device(
SET_MODULE_OWNER(dev);
if (register_netdev(dev) != 0) {
- kfree(dev);
+ free_netdev(dev);
return -EIO;
}
@@ -1322,7 +1322,7 @@ dgrs_found_device(
ret = -EIO;
if (register_netdev(devN)) {
- kfree(devN);
+ free_netdev(devN);
goto fail;
}
privN->chan = i+1;
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index d0fba4cb4df4..76f1d66eb6c1 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -319,7 +319,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_dev:
#endif
- kfree (dev);
+ free_netdev (dev);
err_out_res:
pci_release_regions (pdev);
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 2a14f46f6014..02c2db84f603 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -894,7 +894,7 @@ static int __devinit speedo_found1(struct pci_dev *pdev,
err_free_unlock:
rtnl_unlock();
- kfree(dev);
+ free_netdev(dev);
return -1;
}
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 93fdb1469a0c..00bbf4b7baea 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -565,7 +565,7 @@ err_out_free_res:
#endif
pci_release_regions(pdev);
err_out_free_netdev:
- kfree(dev);
+ free_netdev(dev);
return -ENODEV;
}
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index de914dfc56f8..ee1e45180f86 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -689,7 +689,7 @@ err_out_free_tx:
err_out_free_rx:
pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
err_out_free_dev:
- kfree(dev);
+ free_netdev(dev);
err_out_unmap:
#ifndef USE_IO_OPS
iounmap((void *)ioaddr);
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 36e7074c2bd8..ab87588a7ff3 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -785,7 +785,7 @@ err_out_unmap_tx:
pci_free_consistent(pdev, TX_TOTAL_SIZE, hmp->tx_ring,
hmp->tx_ring_dma);
err_out_cleardev:
- kfree (dev);
+ free_netdev (dev);
err_out_iounmap:
iounmap((char *)ioaddr);
err_out_release:
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index c3b4e5f1353d..d93767489ff0 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -1512,7 +1512,7 @@ out_stop:
out_res:
pci_release_regions(pdev);
out_free:
- kfree(dev);
+ free_netdev(dev);
return err;
}
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index b3045c467da8..6f8c223bf68e 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -1543,7 +1543,7 @@ lan_init_chip(struct parisc_device *dev)
retval = register_netdev(netdevice);
if (retval) {
printk(KERN_WARNING __FILE__ ": register_netdevice ret'd %d\n", retval);
- kfree(netdevice);
+ free_netdev(netdevice);
return -ENODEV;
};
if (dev->id.sversion == 0x72) {
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 7382804af6b0..5dd2b3393edc 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -55,6 +55,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
+
#define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
/* KISS: just allocate small chunks and copy bits.
@@ -152,10 +153,12 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
}
dev->last_rx = jiffies;
- stats->rx_bytes+=skb->len;
- stats->tx_bytes+=skb->len;
- stats->rx_packets++;
- stats->tx_packets++;
+ if (likely(stats)) {
+ stats->rx_bytes+=skb->len;
+ stats->tx_bytes+=skb->len;
+ stats->rx_packets++;
+ stats->tx_packets++;
+ }
netif_rx(skb);
@@ -167,36 +170,35 @@ static struct net_device_stats *get_stats(struct net_device *dev)
return (struct net_device_stats *)dev->priv;
}
-/* Initialize the rest of the LOOPBACK device. */
-int __init loopback_init(struct net_device *dev)
-{
- dev->mtu = (16 * 1024) + 20 + 20 + 12;
- dev->hard_start_xmit = loopback_xmit;
- dev->hard_header = eth_header;
- dev->hard_header_cache = eth_header_cache;
- dev->header_cache_update= eth_header_cache_update;
- dev->hard_header_len = ETH_HLEN; /* 14 */
- dev->addr_len = ETH_ALEN; /* 6 */
- dev->tx_queue_len = 0;
- dev->type = ARPHRD_LOOPBACK; /* 0x0001 */
- dev->rebuild_header = eth_rebuild_header;
- dev->flags = IFF_LOOPBACK;
- dev->features = NETIF_F_SG|NETIF_F_FRAGLIST|NETIF_F_NO_CSUM|NETIF_F_HIGHDMA;
-
- /* Current netfilter will die with oom linearizing large skbs,
- * however this will be cured before 2.5.x is done.
- */
- dev->features |= NETIF_F_TSO;
-
- dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOMEM;
- memset(dev->priv, 0, sizeof(struct net_device_stats));
- dev->get_stats = get_stats;
+struct net_device loopback_dev = {
+ .name = "lo",
+ .mtu = (16 * 1024) + 20 + 20 + 12,
+ .hard_start_xmit = loopback_xmit,
+ .hard_header = eth_header,
+ .hard_header_cache = eth_header_cache,
+ .header_cache_update = eth_header_cache_update,
+ .hard_header_len = ETH_HLEN, /* 14 */
+ .addr_len = ETH_ALEN, /* 6 */
+ .tx_queue_len = 0,
+ .type = ARPHRD_LOOPBACK, /* 0x0001*/
+ .rebuild_header = eth_rebuild_header,
+ .flags = IFF_LOOPBACK,
+ .features = NETIF_F_SG|NETIF_F_FRAGLIST
+ |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA|NETIF_F_TSO,
+};
- /*
- * Fill in the generic fields of the device structure.
- */
-
- return(0);
+/* Setup and register the of the LOOPBACK device. */
+int __init loopback_init(void)
+{
+ struct net_device_stats *stats;
+
+ /* Can survive without statistics */
+ stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
+ if (stats) {
+ memset(stats, 0, sizeof(struct net_device_stats));
+ loopback_dev.priv = stats;
+ loopback_dev.get_stats = &get_stats;
+ }
+
+ return register_netdev(&loopback_dev);
};
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index fe1e255a576c..3e687d9cbd41 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -1324,7 +1324,7 @@ static int __init lp486e_init_module(void) {
dev->base_addr = io;
dev->init = lp486e_probe;
if (register_netdev(dev) != 0) {
- kfree(dev);
+ free_netdev(dev);
return -EIO;
}
dev_lp486e = dev;
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index b95d3030e465..14fbbef63fb6 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -766,7 +766,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
i = pci_request_regions(pdev, dev->name);
if (i) {
- kfree(dev);
+ free_netdev(dev);
return i;
}
@@ -774,7 +774,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
void *mmio = ioremap (ioaddr, iosize);
if (!mmio) {
pci_release_regions(pdev);
- kfree(dev);
+ free_netdev(dev);
return -ENOMEM;
}
ioaddr = (unsigned long) mmio;
@@ -838,7 +838,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
if (i) {
pci_release_regions(pdev);
unregister_netdev(dev);
- kfree(dev);
+ free_netdev(dev);
pci_set_drvdata(pdev, NULL);
return i;
}
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index ad6281ef7a83..2d519b696533 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -529,6 +529,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
struct net_device *dev;
struct pcnet32_access *a = NULL;
u8 promaddr[6];
+ int ret = -ENODEV;
/* reset the chip */
pcnet32_wio_reset(ioaddr);
@@ -540,19 +541,15 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
pcnet32_dwio_reset(ioaddr);
if (pcnet32_dwio_read_csr(ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) {
a = &pcnet32_dwio;
- } else {
- release_region(ioaddr, PCNET32_TOTAL_SIZE);
- return -ENODEV;
- }
+ } else
+ goto err_release_region;
}
chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16);
if (pcnet32_debug > 2)
printk(KERN_INFO " PCnet chip version is %#x.\n", chip_version);
- if ((chip_version & 0xfff) != 0x003) {
- release_region(ioaddr, PCNET32_TOTAL_SIZE);
- return -ENODEV;
- }
+ if ((chip_version & 0xfff) != 0x003)
+ goto err_release_region;
/* initialize variables */
fdx = mii = fset = dxsuflo = ltint = 0;
@@ -614,8 +611,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
default:
printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n",
chip_version);
- release_region(ioaddr, PCNET32_TOTAL_SIZE);
- return -ENODEV;
+ goto err_release_region;
}
/*
@@ -635,8 +631,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
dev = alloc_etherdev(0);
if(!dev) {
- release_region(ioaddr, PCNET32_TOTAL_SIZE);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_release_region;
}
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -708,8 +704,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
dev->base_addr = ioaddr;
/* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) {
- release_region(ioaddr, PCNET32_TOTAL_SIZE);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_free_netdev;
}
memset(lp, 0, sizeof(*lp));
@@ -741,9 +737,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
if (!a) {
printk(KERN_ERR PFX "No access methods\n");
- pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
- release_region(ioaddr, PCNET32_TOTAL_SIZE);
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_free_consistent;
}
lp->a = *a;
@@ -785,14 +780,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
mdelay (1);
dev->irq = probe_irq_off (irq_mask);
- if (dev->irq)
- printk(", probed IRQ %d.\n", dev->irq);
- else {
+ if (!dev->irq) {
printk(", failed to detect IRQ line.\n");
- pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
- release_region(ioaddr, PCNET32_TOTAL_SIZE);
- return -ENODEV;
+ ret = -ENODEV;
+ goto err_free_consistent;
}
+ printk(", probed IRQ %d.\n", dev->irq);
}
/* Set the mii phy_id so that we can query the link state */
@@ -821,6 +814,14 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
printk(KERN_INFO "%s: registered as %s\n",dev->name, lp->name);
cards_found++;
return 0;
+
+err_free_consistent:
+ pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
+err_free_netdev:
+ free_netdev(dev);
+err_release_region:
+ release_region(ioaddr, PCNET32_TOTAL_SIZE);
+ return ret;
}
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index a0b4b659aa0e..c11b83e6adeb 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -454,7 +454,7 @@ err_out_disable:
pci_disable_device(pdev);
err_out:
- kfree(dev);
+ free_netdev(dev);
return rc;
}
@@ -514,7 +514,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
iounmap(ioaddr);
pci_release_regions(pdev);
pci_disable_device(pdev);
- kfree(dev);
+ free_netdev(dev);
return rc;
}
diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c
index f5cdead40f14..e7e1a9f2d71a 100644
--- a/drivers/net/rcpci45.c
+++ b/drivers/net/rcpci45.c
@@ -269,7 +269,7 @@ err_out_free_msgbuf:
pci_free_consistent (pdev, MSG_BUF_SIZE, pDpa->msgbuf,
pDpa->msgbuf_dma);
err_out_free_dev:
- kfree (dev);
+ free_netdev (dev);
err_out:
card_idx--;
return error;
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index d0153f60a036..5326dee62c74 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -213,9 +213,11 @@ sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id)
error = register_netdev(dev);
if (error)
- goto out_release_regions;
+ goto out_free_netdev;
return 0;
+ out_free_netdev:
+ free_netdev(dev);
out_release_regions:
release_region(ioaddr[1], 16);
out_release_region0:
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 1c79e7b9c34e..9f421480b233 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -470,7 +470,7 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out,
rc = pci_set_dma_mask(pdev, 0xffffffffULL);
if (rc)
- goto err_out;
+ goto err_out_disable;
mmio_start = pci_resource_start(pdev, 0);
mmio_end = pci_resource_end(pdev, 0);
@@ -482,18 +482,18 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out,
printk(KERN_ERR PFX
"region #0 not an MMIO resource, aborting\n");
rc = -ENODEV;
- goto err_out;
+ goto err_out_disable;
}
// check for weird/broken PCI region reporting
if (mmio_len < SiS190_MIN_IO_SIZE) {
printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
rc = -ENODEV;
- goto err_out;
+ goto err_out_disable;
}
rc = pci_request_regions(pdev, dev->name);
if (rc)
- goto err_out;
+ goto err_out_disable;
// enable PCI bus-mastering
pci_set_master(pdev);
@@ -521,9 +521,10 @@ SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out,
err_out_free_res:
pci_release_regions(pdev);
-err_out:
+err_out_disable:
pci_disable_device(pdev);
- kfree(dev);
+err_out:
+ free_netdev(dev);
return rc;
}
@@ -603,7 +604,7 @@ SiS190_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
iounmap(ioaddr);
pci_release_regions(pdev);
pci_disable_device(pdev);
- kfree(dev);
+ free_netdev(dev);
return rc;
}
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index b5853f1a9fbd..6422eb2a4208 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -503,7 +503,7 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev
pci_set_drvdata(pci_dev, NULL);
pci_release_regions(pci_dev);
err_out:
- kfree(net_dev);
+ free_netdev(net_dev);
return ret;
}
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index e33c7a2a2f7f..c5a085707302 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -132,7 +132,7 @@ int __init ultramca_probe(struct device *gen_dev)
struct mca_device *mca_dev = to_mca_device(gen_dev);
char slot = mca_dev->slot;
unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff;
- int i;
+ int i, rc;
int adapter = mca_dev->index;
int tbase = 0;
int tirq = 0;
@@ -209,8 +209,9 @@ int __init ultramca_probe(struct device *gen_dev)
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, gen_dev);
- if((i = register_netdev(dev)) != 0)
- return i;
+ rc = register_netdev(dev);
+ if (rc)
+ goto err_free_netdev;
printk(KERN_INFO "%s: %s found in slot %d\n",
dev->name, smc_mca_adapter_names[adapter], slot + 1);
@@ -262,11 +263,15 @@ int __init ultramca_probe(struct device *gen_dev)
}
}
- if (dev->mem_start == 0) /* sanity check, shouldn't happen */
- return -ENODEV;
+ /* sanity check, shouldn't happen */
+ if (dev->mem_start == 0) {
+ rc = -ENODEV;
+ goto err_unregister_netdev;
+ }
- if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name))
- return -EBUSY;
+ rc = request_region(ioaddr, ULTRA_IO_EXTENT, dev->name);
+ if (rc)
+ goto err_unregister_netdev;
reg4 = inb(ioaddr + 4) & 0x7f;
outb(reg4, ioaddr + 4);
@@ -296,10 +301,10 @@ int __init ultramca_probe(struct device *gen_dev)
/* Allocate dev->priv and fill in 8390 specific dev fields.
*/
- if (ethdev_init(dev)) {
+ rc = ethdev_init(dev);
+ if (rc) {
printk (", no memory for dev->priv.\n");
- release_region(ioaddr, ULTRA_IO_EXTENT);
- return -ENOMEM;
+ goto err_release_region;
}
gen_dev->driver_data = dev;
@@ -334,6 +339,14 @@ int __init ultramca_probe(struct device *gen_dev)
NS8390_init(dev, 0);
return 0;
+
+err_release_region:
+ release_region(ioaddr, ULTRA_IO_EXTENT);
+err_unregister_netdev:
+ unregister_netdev(dev);
+err_free_netdev:
+ free_netdev(dev);
+ return rc;
}
static int ultramca_open(struct net_device *dev)
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index dcf1db7ea6ef..c2bddf1f1700 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -1070,7 +1070,7 @@ err_out_cleardev:
err_out_free_res:
pci_release_regions (pdev);
err_out_free_netdev:
- kfree(dev);
+ free_netdev(dev);
return -ENODEV;
}
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 5bd8be316547..aad877c5400b 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -734,7 +734,7 @@ err_out_res:
#endif
pci_release_regions(pdev);
err_out_netdev:
- kfree (dev);
+ free_netdev (dev);
return -ENODEV;
}
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index a452e5942b52..a346fd1d4dba 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2416,13 +2416,6 @@ static int gem_nway_reset(struct net_device *dev)
return 0;
}
-static u32 gem_get_link(struct net_device *dev)
-{
- struct gem *gp = dev->priv;
-
- return (gp->lstate == link_up);
-}
-
static u32 gem_get_msglevel(struct net_device *dev)
{
struct gem *gp = dev->priv;
@@ -2441,7 +2434,6 @@ static struct ethtool_ops gem_ethtool_ops = {
.get_settings = gem_get_settings,
.set_settings = gem_set_settings,
.nway_reset = gem_nway_reset,
- .get_link = gem_get_link,
.get_msglevel = gem_get_msglevel,
.set_msglevel = gem_set_msglevel,
};
@@ -2630,7 +2622,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, "
"aborting.\n");
- return err;
+ goto err_disable_device;
}
pci_using_dac = 0;
}
@@ -2641,20 +2633,23 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) {
printk(KERN_ERR PFX "Cannot find proper PCI device "
"base address, aborting.\n");
- return -ENODEV;
+ err = -ENODEV;
+ goto err_disable_device;
}
dev = alloc_etherdev(sizeof(*gp));
if (!dev) {
printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto err_disable_device;
}
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
gp = dev->priv;
- if (pci_request_regions(pdev, dev->name)) {
+ err = pci_request_regions(pdev, dev->name);
+ if (err) {
printk(KERN_ERR PFX "Cannot obtain PCI resources, "
"aborting.\n");
goto err_out_free_netdev;
@@ -2688,6 +2683,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
if (gp->regs == 0UL) {
printk(KERN_ERR PFX "Cannot map device registers, "
"aborting.\n");
+ err = -EIO;
goto err_out_free_res;
}
@@ -2711,8 +2707,10 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
/* By default, we start with autoneg */
gp->want_autoneg = 1;
- if (gem_check_invariants(gp))
+ if (gem_check_invariants(gp)) {
+ err = -ENODEV;
goto err_out_iounmap;
+ }
/* It is guaranteed that the returned buffer will be at least
* PAGE_SIZE aligned.
@@ -2723,6 +2721,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
if (!gp->init_block) {
printk(KERN_ERR PFX "Cannot allocate init block, "
"aborting.\n");
+ err = -ENOMEM;
goto err_out_iounmap;
}
@@ -2735,6 +2734,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
if (register_netdev(dev)) {
printk(KERN_ERR PFX "Cannot register net device, "
"aborting.\n");
+ err = -ENOMEM;
goto err_out_free_consistent;
}
@@ -2804,9 +2804,10 @@ err_out_free_res:
pci_release_regions(pdev);
err_out_free_netdev:
- kfree(dev);
-
- return -ENODEV;
+ free_netdev(dev);
+err_disable_device:
+ pci_disable_device(pdev);
+ return err;
}
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 8c786ab7b3c5..b91f7d0199bf 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2895,7 +2895,7 @@ err_out_iounmap:
sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE);
err_out_free_netdev:
- kfree(dev);
+ free_netdev(dev);
err_out:
return err;
@@ -3247,7 +3247,7 @@ err_out_clear_quattro:
if (qp != NULL)
qp->happy_meals[qfe_slot] = NULL;
- kfree(dev);
+ free_netdev(dev);
err_out:
return err;
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index b5d8879c2035..5116b5152e8a 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -949,7 +949,7 @@ out1:
i = 4;
out:
while (i--)
- kfree(qe_devs[i]);
+ free_netdev(qe_devs[i]);
return res;
}
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index c31dc44a6fd2..3ebedccf00b3 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -7740,7 +7740,7 @@ err_out_iounmap:
iounmap((void *) tp->regs);
err_out_free_dev:
- kfree(dev);
+ free_netdev(dev);
err_out_free_res:
pci_release_regions(pdev);
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 5a45900a816e..c5b6999712fb 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -670,7 +670,7 @@ err_out_uninit:
pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage,
priv->dmaStorageDMA );
err_out_free_dev:
- kfree(dev);
+ free_netdev(dev);
err_out_regions:
if (pdev)
pci_release_regions(pdev);
@@ -695,7 +695,7 @@ static void TLan_Eisa_Cleanup(void)
release_region( dev->base_addr, 0x10);
unregister_netdev( dev );
TLan_Eisa_Devices = priv->nextDevice;
- kfree( dev );
+ free_netdev( dev );
tlan_have_eisa--;
}
}
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index e83372b7adbb..f30b72218b30 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -2455,7 +2455,7 @@ error_out_remap:
error_out_regions:
pci_release_regions(pdev);
error_out_dev:
- kfree(dev);
+ free_netdev(dev);
error_out:
return err;
}
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index c247af6bf6ad..3059d04aaf0d 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -868,7 +868,7 @@ err_out_free_res:
#endif
pci_release_regions(pdev);
err_out_free_netdev:
- kfree (dev);
+ free_netdev (dev);
err_out:
return -ENODEV;
}
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 5aab67436cc7..380bb830d738 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -55,14 +55,13 @@
#include <asm/dma.h>
#include <asm/uaccess.h>
-static const char devname[] = "dlci";
static const char version[] = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org";
-static struct net_device *open_dev[CONFIG_DLCI_COUNT];
-
+static LIST_HEAD(dlci_devs);
+static spinlock_t dlci_dev_lock = SPIN_LOCK_UNLOCKED;
static char *basename[16];
-int dlci_init(struct net_device *dev);
+static void dlci_setup(struct net_device *);
/* allow FRAD's to register their name as a valid FRAD */
int register_frad(const char *name)
@@ -115,6 +114,7 @@ int unregister_frad(const char *name)
return(0);
}
+EXPORT_SYMBOL(unregister_frad);
/*
* these encapsulate the RFC 1490 requirements as well as
@@ -168,6 +168,14 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
int process, header;
dlp = dev->priv;
+ if (!pskb_may_pull(skb, sizeof(*hdr))) {
+ printk(KERN_NOTICE "%s: invalid data no header\n",
+ dev->name);
+ dlp->stats.rx_errors++;
+ kfree_skb(skb);
+ return;
+ }
+
hdr = (struct frhdr *) skb->data;
process = 0;
header = 0;
@@ -277,7 +285,7 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev)
return(ret);
}
-int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get)
+static int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get)
{
struct dlci_conf config;
struct dlci_local *dlp;
@@ -311,7 +319,7 @@ int dlci_config(struct net_device *dev, struct dlci_conf *conf, int get)
return(0);
}
-int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct dlci_local *dlp;
@@ -401,21 +409,23 @@ static struct net_device_stats *dlci_get_stats(struct net_device *dev)
return(&dlp->stats);
}
-int dlci_add(struct dlci_add *dlci)
+static int dlci_add(struct dlci_add *dlci)
{
- struct net_device *master, *slave;
+ struct net_device *master, *slave;
struct dlci_local *dlp;
struct frad_local *flp;
int err, i;
- char buf[10];
+
/* validate slave device */
- slave = __dev_get_by_name(dlci->devname);
+ slave = dev_get_by_name(dlci->devname);
if (!slave)
return(-ENODEV);
- if (slave->type != ARPHRD_FRAD)
+ if (slave->type != ARPHRD_FRAD) {
+ dev_put(slave);
return(-EINVAL);
+ }
/* check for registration */
for (i=0;i<sizeof(basename) / sizeof(char *); i++)
@@ -424,33 +434,22 @@ int dlci_add(struct dlci_add *dlci)
(strlen(dlci->devname) > strlen(basename[i])))
break;
- if (i == sizeof(basename) / sizeof(char *))
+ if (i == sizeof(basename) / sizeof(char *)) {
+ dev_put(slave);
return(-EINVAL);
-
- /* check for too many open devices : should this be dynamic ? */
- for(i=0;i<CONFIG_DLCI_COUNT;i++)
- if (!open_dev[i])
- break;
-
- if (i == CONFIG_DLCI_COUNT)
- return(-ENOSPC); /* #### Alan: Comments on this?? */
+ }
/* create device name */
- sprintf(buf, "%s%02i", devname, i);
-
- master = kmalloc(sizeof(*master), GFP_KERNEL);
- if (!master)
+ master = alloc_netdev( sizeof(struct dlci_local), "dlci%d",
+ dlci_setup);
+ if (!master) {
+ dev_put(slave);
return(-ENOMEM);
-
- memset(master, 0, sizeof(*master));
-
- strcpy(master->name, buf);
- master->init = dlci_init;
- master->flags = 0;
+ }
err = register_netdev(master);
- if (err < 0)
- {
+ if (err < 0) {
+ dev_put(slave);
kfree(master);
return(err);
}
@@ -459,64 +458,65 @@ int dlci_add(struct dlci_add *dlci)
dlp = (struct dlci_local *) master->priv;
dlp->slave = slave;
+ dlp->master = master;
flp = slave->priv;
err = flp ? (*flp->assoc)(slave, master) : -EINVAL;
if (err < 0)
{
unregister_netdev(master);
- kfree(master->priv);
- kfree(master);
+ dev_put(slave);
+ free_netdev(master);
return(err);
}
- strcpy(dlci->devname, buf);
- open_dev[i] = master;
- MOD_INC_USE_COUNT;
+ strcpy(dlci->devname, master->name);
+
+ spin_lock_bh(&dlci_dev_lock);
+ list_add(&dlp->list, &dlci_devs);
+ spin_unlock_bh(&dlci_dev_lock);
+
return(0);
}
-int dlci_del(struct dlci_add *dlci)
+static int dlci_del(struct dlci_add *dlci)
{
struct dlci_local *dlp;
struct frad_local *flp;
- struct net_device *master, *slave;
- int i, err;
+ struct net_device *master, *slave;
+ int err;
/* validate slave device */
master = __dev_get_by_name(dlci->devname);
if (!master)
return(-ENODEV);
- if (netif_running(master))
+ if (netif_running(master)) {
return(-EBUSY);
+ }
dlp = master->priv;
slave = dlp->slave;
flp = slave->priv;
err = (*flp->deassoc)(slave, master);
- if (err)
+ if (err)
return(err);
- unregister_netdev(master);
- for(i=0;i<CONFIG_DLCI_COUNT;i++)
- if (master == open_dev[i])
- break;
+ spin_lock_bh(&dlci_dev_lock);
+ list_del(&dlp->list);
+ spin_unlock_bh(&dlci_dev_lock);
- if (i<CONFIG_DLCI_COUNT)
- open_dev[i] = NULL;
+ unregister_netdev(master);
- kfree(master->priv);
+ dev_put(slave);
free_netdev(master);
- MOD_DEC_USE_COUNT;
-
return(0);
}
-int dlci_ioctl(unsigned int cmd, void *arg)
+static int dlci_ioctl(unsigned int cmd, void *arg)
{
struct dlci_add add;
int err;
@@ -548,16 +548,9 @@ int dlci_ioctl(unsigned int cmd, void *arg)
return(err);
}
-int dlci_init(struct net_device *dev)
+static void dlci_setup(struct net_device *dev)
{
- struct dlci_local *dlp;
-
- dev->priv = kmalloc(sizeof(struct dlci_local), GFP_KERNEL);
- if (!dev->priv)
- return(-ENOMEM);
-
- memset(dev->priv, 0, sizeof(struct dlci_local));
- dlp = dev->priv;
+ struct dlci_local *dlp = dev->priv;
dev->flags = 0;
dev->open = dlci_open;
@@ -573,9 +566,7 @@ int dlci_init(struct net_device *dev)
dev->type = ARPHRD_DLCI;
dev->hard_header_len = sizeof(struct frhdr);
dev->addr_len = sizeof(short);
- memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
- return(0);
}
int __init init_dlci(void)
@@ -584,9 +575,6 @@ int __init init_dlci(void)
dlci_ioctl_set(dlci_ioctl);
printk("%s.\n", version);
-
- for(i=0;i<CONFIG_DLCI_COUNT;i++)
- open_dev[i] = NULL;
for(i=0;i<sizeof(basename) / sizeof(char *);i++)
basename[i] = NULL;
@@ -596,7 +584,16 @@ int __init init_dlci(void)
void __exit dlci_exit(void)
{
+ struct dlci_local *dlp, *nxt;
+
dlci_ioctl_set(NULL);
+
+ list_for_each_entry_safe(dlp, nxt, &dlci_devs, list) {
+ unregister_netdev(dlp->master);
+ dev_put(dlp->slave);
+ free_netdev(dlp->master);
+ }
+
}
module_init(init_dlci);
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 349400d4d95a..81b2f271036c 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -140,6 +140,7 @@ static void change_level( struct net_device * );
static void timeout_change_level( struct net_device * );
static u32 calc_crc32( u32, u8 *, u32 );
static struct sk_buff * get_rx_buf( struct net_device * );
+static int sbni_init( struct net_device * );
#ifdef CONFIG_SBNI_MULTILINE
static int enslave( struct net_device *, struct net_device * );
@@ -205,23 +206,44 @@ sbni_isa_probe( struct net_device *dev )
}
}
-
-int __init
-sbni_probe( struct net_device *dev )
+static void __init sbni_devsetup(struct net_device *dev)
{
- int i;
+ ether_setup( dev );
+ dev->init = &sbni_init;
+ dev->open = &sbni_open;
+ dev->stop = &sbni_close;
+ dev->hard_start_xmit = &sbni_start_xmit;
+ dev->get_stats = &sbni_get_stats;
+ dev->set_multicast_list = &set_multicast_list;
+ dev->do_ioctl = &sbni_ioctl;
+
+ SET_MODULE_OWNER( dev );
+}
+int __init sbni_probe(void)
+{
+ struct net_device *dev;
static unsigned version_printed __initdata = 0;
+
if( version_printed++ == 0 )
printk( KERN_INFO "%s", version );
- if( !dev ) { /* simple sanity check */
- printk( KERN_ERR "sbni: NULL device!\n" );
- return -ENODEV;
- }
+ dev = alloc_netdev(sizeof(struct net_local), "sbni%d", sbni_devsetup);
+ if (!dev)
+ return -ENOMEM;
- SET_MODULE_OWNER( dev );
+ netdev_boot_setup_check(dev);
+
+ if (register_netdev(dev)) {
+ kfree(dev);
+ return -ENODEV;
+ }
+ return 0;
+}
+static int __init sbni_init(struct net_device *dev)
+{
+ int i;
if( dev->base_addr )
return sbni_isa_probe( dev );
/* otherwise we have to perform search our adapter */
@@ -338,7 +360,7 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
dev->base_addr = ioaddr;
/* Allocate dev->priv and fill in sbni-specific dev fields. */
- nl = (struct net_local *) kmalloc(sizeof(struct net_local), GFP_KERNEL);
+ nl = dev->priv;
if( !nl ) {
printk( KERN_ERR "%s: unable to get memory!\n", dev->name );
release_region( ioaddr, SBNI_IO_EXTENT );
@@ -389,14 +411,6 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
nl->link = NULL;
#endif
- dev->open = &sbni_open;
- dev->stop = &sbni_close;
- dev->hard_start_xmit = &sbni_start_xmit;
- dev->get_stats = &sbni_get_stats;
- dev->set_multicast_list = &set_multicast_list;
- dev->do_ioctl = &sbni_ioctl;
- ether_setup( dev );
-
sbni_cards[ num++ ] = dev;
return dev;
}
@@ -1478,15 +1492,15 @@ init_module( void )
struct net_device *dev;
while( num < SBNI_MAX_NUM_CARDS ) {
- if( !(dev = kmalloc(sizeof(struct net_device), GFP_KERNEL)) ){
+ dev = alloc_netdev(sizeof(struct net_local),
+ "sbni%d", sbni_devsetup);
+ if( !dev) {
printk( KERN_ERR "sbni: unable to allocate device!\n" );
return -ENOMEM;
}
- memset( dev, 0, sizeof(struct net_device) );
sprintf( dev->name, "sbni%d", num );
- dev->init = sbni_probe;
if( register_netdev( dev ) ) {
kfree( dev );
break;
@@ -1506,7 +1520,6 @@ cleanup_module( void )
if( (dev = sbni_cards[ num ]) != NULL ) {
unregister_netdev( dev );
release_region( dev->base_addr, SBNI_IO_EXTENT );
- kfree( dev->priv );
free_netdev( dev );
}
}
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 8079d8b5ddee..c91e59da2ed9 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -71,6 +71,8 @@ static unsigned int valid_mem[] __initdata = {
0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000,
0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000};
+static spinlock_t sdla_lock = SPIN_LOCK_UNLOCKED;
+
/*********************************************************
*
* these are the core routines that access the card itself
@@ -79,10 +81,10 @@ static unsigned int valid_mem[] __initdata = {
#define SDLA_WINDOW(dev,addr) outb((((addr) >> 13) & 0x1F), (dev)->base_addr + SDLA_REG_Z80_WINDOW)
-static void sdla_read(struct net_device *dev, int addr, void *buf, short len)
+static void __sdla_read(struct net_device *dev, int addr, void *buf, short len)
{
- unsigned long flags;
- char *temp, *base;
+ char *temp;
+ const void *base;
int offset, bytes;
temp = buf;
@@ -90,13 +92,10 @@ static void sdla_read(struct net_device *dev, int addr, void *buf, short len)
{
offset = addr & SDLA_ADDR_MASK;
bytes = offset + len > SDLA_WINDOW_SIZE ? SDLA_WINDOW_SIZE - offset : len;
- base = (void *) (dev->mem_start + offset);
+ base = (const void *) (dev->mem_start + offset);
- save_flags(flags);
- cli();
SDLA_WINDOW(dev, addr);
memcpy(temp, base, bytes);
- restore_flags(flags);
addr += bytes;
temp += bytes;
@@ -104,10 +103,19 @@ static void sdla_read(struct net_device *dev, int addr, void *buf, short len)
}
}
-static void sdla_write(struct net_device *dev, int addr, void *buf, short len)
+static void sdla_read(struct net_device *dev, int addr, void *buf, short len)
{
unsigned long flags;
- char *temp, *base;
+ spin_lock_irqsave(&sdla_lock, flags);
+ __sdla_read(dev, addr, buf, len);
+ spin_unlock_irqrestore(&sdla_lock, flags);
+}
+
+static void __sdla_write(struct net_device *dev, int addr,
+ const void *buf, short len)
+{
+ const char *temp;
+ void *base;
int offset, bytes;
temp = buf;
@@ -116,17 +124,27 @@ static void sdla_write(struct net_device *dev, int addr, void *buf, short len)
offset = addr & SDLA_ADDR_MASK;
bytes = offset + len > SDLA_WINDOW_SIZE ? SDLA_WINDOW_SIZE - offset : len;
base = (void *) (dev->mem_start + offset);
- save_flags(flags);
- cli();
+
SDLA_WINDOW(dev, addr);
memcpy(base, temp, bytes);
- restore_flags(flags);
+
addr += bytes;
temp += bytes;
len -= bytes;
}
}
+static void sdla_write(struct net_device *dev, int addr,
+ const void *buf, short len)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sdla_lock, flags);
+ __sdla_write(dev, addr, buf, len);
+ spin_unlock_irqrestore(&sdla_lock, flags);
+}
+
+
static void sdla_clear(struct net_device *dev)
{
unsigned long flags;
@@ -138,8 +156,7 @@ static void sdla_clear(struct net_device *dev)
bytes = SDLA_WINDOW_SIZE;
base = (void *) dev->mem_start;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&sdla_lock, flags);
while(len)
{
SDLA_WINDOW(dev, addr);
@@ -148,7 +165,8 @@ static void sdla_clear(struct net_device *dev)
addr += bytes;
len -= bytes;
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&sdla_lock, flags);
+
}
static char sdla_byte(struct net_device *dev, int addr)
@@ -158,11 +176,10 @@ static char sdla_byte(struct net_device *dev, int addr)
temp = (void *) (dev->mem_start + (addr & SDLA_ADDR_MASK));
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&sdla_lock, flags);
SDLA_WINDOW(dev, addr);
byte = *temp;
- restore_flags(flags);
+ spin_unlock_irqrestore(&sdla_lock, flags);
return(byte);
}
@@ -414,7 +431,8 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
struct frad_local *flp;
struct sdla_cmd *cmd_buf;
unsigned long pflags;
- int jiffs, ret, waiting, len;
+ unsigned long jiffs;
+ int ret, waiting, len;
long window;
flp = dev->priv;
@@ -423,8 +441,8 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
ret = 0;
len = 0;
jiffs = jiffies + HZ; /* 1 second is plenty */
- save_flags(pflags);
- cli();
+
+ spin_lock_irqsave(&sdla_lock, pflags);
SDLA_WINDOW(dev, window);
cmd_buf->cmd = cmd;
cmd_buf->dlci = dlci;
@@ -436,7 +454,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
cmd_buf->length = inlen;
cmd_buf->opp_flag = 1;
- restore_flags(pflags);
+ spin_unlock_irqrestore(&sdla_lock, pflags);
waiting = 1;
len = 0;
@@ -444,18 +462,17 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
{
if (waiting++ % 3)
{
- save_flags(pflags);
- cli();
+ spin_lock_irqsave(&sdla_lock, pflags);
SDLA_WINDOW(dev, window);
waiting = ((volatile int)(cmd_buf->opp_flag));
- restore_flags(pflags);
+ spin_unlock_irqrestore(&sdla_lock, pflags);
}
}
if (!waiting)
{
- save_flags(pflags);
- cli();
+
+ spin_lock_irqsave(&sdla_lock, pflags);
SDLA_WINDOW(dev, window);
ret = cmd_buf->retval;
len = cmd_buf->length;
@@ -471,7 +488,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
if (ret)
memcpy(&status, cmd_buf->data, len > sizeof(status) ? sizeof(status) : len);
- restore_flags(pflags);
+ spin_unlock_irqrestore(&sdla_lock, pflags);
}
else
ret = SDLA_RET_TIMEOUT;
@@ -555,7 +572,6 @@ int sdla_assoc(struct net_device *slave, struct net_device *master)
if (i == CONFIG_DLCI_MAX)
return(-EMLINK); /* #### Alan: Comments on this ?? */
- MOD_INC_USE_COUNT;
flp->master[i] = master;
flp->dlci[i] = -*(short *)(master->dev_addr);
@@ -588,7 +604,6 @@ int sdla_deassoc(struct net_device *slave, struct net_device *master)
flp->master[i] = NULL;
flp->dlci[i] = 0;
- MOD_DEC_USE_COUNT;
if (netif_running(slave)) {
if (flp->config.station == FRAD_STATION_CPE)
@@ -688,14 +703,14 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev)
ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size);
if (ret == SDLA_RET_OK)
{
- save_flags(flags);
- cli();
+
+ spin_lock_irqsave(&sdla_lock, flags);
SDLA_WINDOW(dev, addr);
pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
- sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
- SDLA_WINDOW(dev, addr);
+ __sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
+ SDLA_WINDOW(dev, addr);
pbuf->opp_flag = 1;
- restore_flags(flags);
+ spin_unlock_irqrestore(&sdla_lock, flags);
}
break;
}
@@ -753,8 +768,7 @@ static void sdla_receive(struct net_device *dev)
pbufi = NULL;
pbuf = NULL;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&sdla_lock, flags);
switch (flp->type)
{
@@ -821,7 +835,7 @@ static void sdla_receive(struct net_device *dev)
case SDLA_S502A:
case SDLA_S502E:
if (success)
- sdla_read(dev, SDLA_502_RCV_BUF + SDLA_502_DATA_OFS, skb_put(skb,len), len);
+ __sdla_read(dev, SDLA_502_RCV_BUF + SDLA_502_DATA_OFS, skb_put(skb,len), len);
SDLA_WINDOW(dev, SDLA_502_RCV_BUF);
cmd->opp_flag = 0;
@@ -834,9 +848,9 @@ static void sdla_receive(struct net_device *dev)
split = addr + len > buf_top + 1 ? len - (buf_top - addr + 1) : 0;
len2 = len - split;
- sdla_read(dev, addr, skb_put(skb, len2), len2);
+ __sdla_read(dev, addr, skb_put(skb, len2), len2);
if (split)
- sdla_read(dev, buf_base, skb_put(skb, split), split);
+ __sdla_read(dev, buf_base, skb_put(skb, split), split);
}
/* increment the buffer we're looking at */
@@ -853,7 +867,7 @@ static void sdla_receive(struct net_device *dev)
(*dlp->receive)(skb, master);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&sdla_lock, flags);
}
static irqreturn_t sdla_isr(int irq, void *dev_id, struct pt_regs * regs)
@@ -979,8 +993,6 @@ static int sdla_close(struct net_device *dev)
netif_stop_queue(dev);
- MOD_DEC_USE_COUNT;
-
return(0);
}
@@ -1082,8 +1094,6 @@ static int sdla_open(struct net_device *dev)
netif_start_queue(dev);
- MOD_INC_USE_COUNT;
-
return(0);
}
@@ -1614,19 +1624,30 @@ static struct net_device_stats *sdla_stats(struct net_device *dev)
return(&flp->stats);
}
-int __init sdla_init(struct net_device *dev)
+static void setup_sdla(struct net_device *dev)
{
+ dev->flags = 0;
+ dev->type = 0xFFFF;
+ dev->hard_header_len = 0;
+ dev->addr_len = 0;
+ dev->mtu = SDLA_MAX_MTU;
+}
+
+struct net_device * __init sdla_init(void)
+{
+ struct net_device *dev;
struct frad_local *flp;
+ int err = -ENOMEM;
- /* allocate the private data structure */
- flp = kmalloc(sizeof(struct frad_local), GFP_KERNEL);
- if (!flp)
- return(-ENOMEM);
+ dev = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla);
+ if (!dev)
+ goto out;
- memset(flp, 0, sizeof(struct frad_local));
- dev->priv = flp;
+ SET_MODULE_OWNER(dev);
+ netdev_boot_setup_check(dev);
+
+ flp = dev->priv;
- dev->flags = 0;
dev->open = sdla_open;
dev->stop = sdla_close;
dev->do_ioctl = sdla_ioctl;
@@ -1635,12 +1656,6 @@ int __init sdla_init(struct net_device *dev)
dev->hard_start_xmit = sdla_transmit;
dev->change_mtu = sdla_change_mtu;
- dev->type = 0xFFFF;
- dev->hard_header_len = 0;
- dev->addr_len = 0;
- dev->mtu = SDLA_MAX_MTU;
- SET_MODULE_OWNER(dev);
-
flp->activate = sdla_activate;
flp->deactivate = sdla_deactivate;
flp->assoc = sdla_assoc;
@@ -1652,7 +1667,14 @@ int __init sdla_init(struct net_device *dev)
flp->timer.data = (unsigned long) dev;
flp->timer.function = sdla_poll;
- return(0);
+ err = register_netdev(dev);
+ if (err)
+ goto out1;
+ return dev;
+out1:
+ kfree(dev);
+out:
+ return ERR_PTR(err);
}
int __init sdla_c_setup(void)
@@ -1663,10 +1685,7 @@ int __init sdla_c_setup(void)
}
#ifdef MODULE
-static struct net_device sdla0 = {
- .name = "sdla0",
- .init = sdla_init
-};
+static struct net_device *sdla0;
#endif /* MODULE */
static int __init init_sdla(void)
@@ -1675,7 +1694,9 @@ static int __init init_sdla(void)
sdla_c_setup();
#ifdef MODULE
- result = register_netdev(&sdla0);
+ sdla0 = sdla_init();
+ if (IS_ERR(sdla0))
+ result = PTR_ERR(sdla0);
#endif
return result;
}
@@ -1683,11 +1704,10 @@ static int __init init_sdla(void)
static void __exit exit_sdla(void)
{
#ifdef MODULE
- unregister_netdev(&sdla0);
- if (sdla0.priv)
- kfree(sdla0.priv);
- if (sdla0.irq)
- free_irq(sdla0.irq, &sdla0);
+ unregister_netdev(sdla0);
+ if (sdla0->irq)
+ free_irq(sdla0->irq, sdla0);
+ free_netdev(sdla0);
#endif
}
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 8a3328687d1f..c22ca46b0d81 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -577,7 +577,7 @@ err_out_free_res:
#endif
pci_release_regions(pdev);
err_out_free_netdev:
- kfree (dev);
+ free_netdev (dev);
return -ENODEV;
}
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 60bb81d4649b..4e384344042c 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1758,7 +1758,7 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *))
printk("53c700: scsi%d, command ", SCp->device->host->host_no);
print_command(SCp->cmnd);
#endif
- if(SCp->device->tagged_supported && !SCp->device->tagged_queue
+ if(SCp->device->tagged_supported && !SCp->device->simple_tags
&& (hostdata->tag_negotiated &(1<<SCp->device->id)) == 0
&& NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) {
/* upper layer has indicated tags are supported. We don't
diff --git a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c
index 85d4d0507546..904115d0eac3 100644
--- a/drivers/scsi/AM53C974.c
+++ b/drivers/scsi/AM53C974.c
@@ -1231,8 +1231,8 @@ static void AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs)
hostdata->sel_cmd = NULL;
hostdata->selecting = 0;
#ifdef SCSI2
- if (!hostdata->connected->device->tagged_queue)
-#endif
+ if (!hostdata->conneted->device->simple_tags)
+#else
hostdata->busy[hostdata->connected->device->id] |= (1 << hostdata->connected->device->lun);
/* very strange -- use_sg is sometimes nonzero for request sense commands !! */
if ((hostdata->connected->cmnd[0] == REQUEST_SENSE) && hostdata->connected->use_sg) {
@@ -1811,7 +1811,7 @@ static int AM53C974_message(struct Scsi_Host *instance, Scsi_Cmnd * cmd,
case HEAD_OF_QUEUE_TAG:
case ORDERED_QUEUE_TAG:
case SIMPLE_QUEUE_TAG:
- cmd->device->tagged_queue = 0;
+ cmd->device->simple_tags = 0;
hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
break;
default:
@@ -1958,7 +1958,7 @@ static void AM53C974_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag
#endif
#ifdef SCSI2
- if (cmd->device->tagged_queue && (tag != TAG_NONE)) {
+ if (cmd->device->simple_tags && (tag != TAG_NONE)) {
tmp[1] = SIMPLE_QUEUE_TAG;
if (tag == TAG_NEXT) {
/* 0 is TAG_NONE, used to imply no tag for this command */
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 315967cc013a..b3c9048c3a17 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -22,6 +22,17 @@ config SCSI
module if your root file system (the one containing the directory /)
is located on a SCSI device.
+config SCSI_PROC_FS
+ bool "legacy /proc/scsi/ support"
+ depends on SCSI
+ default y
+ ---help---
+ This option enables support for the various files in
+ /proc/scsi. In Linux 2.6 this has been superceeded by
+ files in sysfs but many legacy applications rely on this.
+
+ If unusure say Y.
+
comment "SCSI support type (disk, tape, CD-ROM)"
depends on SCSI
@@ -726,13 +737,13 @@ config IBMMCA_SCSI_DEV_RESET
config SCSI_IPS
tristate "IBM ServeRAID support"
- depends on X86 && PCI && SCSI
+ depends on PCI && SCSI
---help---
This is support for the IBM ServeRAID hardware RAID controllers.
See <http://www.developer.ibm.com/welcome/netfinity/serveraid.html>
for more information. If this driver does not work correctly
without modification please contact the author by email at
- ipslinux@us.ibm.com.
+ ipslinux@adaptec.com.
You can build this driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
@@ -989,36 +1000,9 @@ config SCSI_NCR_Q720
Unless you have an NCR manufactured machine, the chances are that
you do not have this SCSI card, so say N.
-config SCSI_SYM53C8XX
- tristate "SYM53C8XX SCSI support"
- depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI
- ---help---
- This driver supports all the features of recent 53C8XX chips (used
- in PCI SCSI controllers), notably the hardware phase mismatch
- feature of the SYM53C896.
-
- Older versions of the 53C8XX chips are not supported by this
- driver. If your system uses either a 810 rev. < 16, a 815, or a 825
- rev. < 16 PCI SCSI processor, you must use the generic NCR53C8XX
- driver ("NCR53C8XX SCSI support" above) or configure both the
- NCR53C8XX and this SYM53C8XX drivers either as module or linked to
- the kernel image.
-
- When both drivers are linked into the kernel, the SYM53C8XX driver
- is called first at initialization and you can use the 'excl=ioaddr'
- driver boot option to exclude attachment of adapters by the
- SYM53C8XX driver. For example, entering
- 'sym53c8xx=excl:0xb400,excl=0xc000' at the lilo prompt prevents
- adapters at io address 0xb400 and 0xc000 from being attached by the
- SYM53C8XX driver, thus allowing the NCR53C8XX driver to attach them.
- The 'excl' option is also supported by the NCR53C8XX driver.
-
- Please read <file:Documentation/scsi/ncr53c8xx.txt> for more
- information.
-
config SCSI_NCR53C8XX_DEFAULT_TAGS
int " default tagged command queue depth"
- depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720)
+ depends on SCSI_ZALON || SCSI_NCR_Q720
default "8"
---help---
"Tagged command queuing" is a feature of SCSI-2 which improves
@@ -1044,7 +1028,7 @@ config SCSI_NCR53C8XX_DEFAULT_TAGS
config SCSI_NCR53C8XX_MAX_TAGS
int " maximum number of queued commands"
- depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720)
+ depends on SCSI_ZALON || SCSI_NCR_Q720
default "32"
---help---
This option allows you to specify the maximum number of commands
@@ -1061,7 +1045,7 @@ config SCSI_NCR53C8XX_MAX_TAGS
config SCSI_NCR53C8XX_SYNC
int " synchronous transfers frequency in MHz"
- depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720)
+ depends on SCSI_ZALON || SCSI_NCR_Q720
default "20"
---help---
The SCSI Parallel Interface-2 Standard defines 5 classes of transfer
@@ -1095,7 +1079,7 @@ config SCSI_NCR53C8XX_SYNC
config SCSI_NCR53C8XX_PROFILE
bool " enable profiling"
- depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720)
+ depends on SCSI_ZALON || SCSI_NCR_Q720
help
This option allows you to enable profiling information gathering.
These statistics are not very accurate due to the low frequency
@@ -1104,34 +1088,9 @@ config SCSI_NCR53C8XX_PROFILE
The normal answer therefore is N.
-config SCSI_NCR53C8XX_IOMAPPED
- bool " use normal IO"
- depends on SCSI_SYM53C8XX && !(SCSI_ZALON || SCSI_NCR_Q720)
- help
- If you say Y here, the driver will use normal IO, as opposed to
- memory mapped IO. Memory mapped IO has less latency than normal IO
- and works for most Intel-based hardware. Under Linux/Alpha only
- normal IO is currently supported by the driver and so, this option
- has no effect on those systems.
-
- The normal answer therefore is N; try Y only if you encounter SCSI
- related problems.
-
-config SCSI_NCR53C8XX_PQS_PDS
- bool " include support for the NCR PQS/PDS SCSI card"
- depends on SCSI_SYM53C8XX
- help
- Say Y here if you have a special SCSI adapter produced by NCR
- corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need
- this if you do not have one of these adapters. However, since this
- device is detected as a specific PCI device, this option is quite
- safe.
-
- The common answer here is N, but answering Y is safe.
-
config SCSI_NCR53C8XX_NO_DISCONNECT
bool " not allow targets to disconnect"
- depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
+ depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
help
This option is only provided for safety if you suspect some SCSI
device of yours to not support properly the target-disconnect
@@ -1139,26 +1098,6 @@ config SCSI_NCR53C8XX_NO_DISCONNECT
not allow targets to disconnect is not reasonable if there is more
than 1 device on a SCSI bus. The normal answer therefore is N.
-config SCSI_NCR53C8XX_SYMBIOS_COMPAT
- bool " assume boards are SYMBIOS compatible (EXPERIMENTAL)"
- depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720 ) && EXPERIMENTAL
- ---help---
- This option allows you to enable some features depending on GPIO
- wiring. These General Purpose Input/Output pins can be used for
- vendor specific features or implementation of the standard SYMBIOS
- features. Genuine SYMBIOS controllers use GPIO0 in output for
- controller LED and GPIO3 bit as a flag indicating
- singled-ended/differential interface. The Tekram DC-390U/F boards
- uses a different GPIO wiring.
-
- Your answer to this question is ignored if all your controllers have
- NVRAM, since the driver is able to detect the board type from the
- NVRAM format.
-
- If all the controllers in your system are genuine SYMBIOS boards or
- use BIOS and drivers from SYMBIOS, you would want to say Y here,
- otherwise N. N is the safe answer.
-
config SCSI_MCA_53C9X
tristate "NCR MCA 53C9x SCSI support"
depends on MCA && SCSI && BROKEN_ON_SMP
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index b2ed067c7b98..fb2442aeb330 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -126,7 +126,8 @@ scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \
scsicam.o scsi_error.o scsi_lib.o \
scsi_scan.o scsi_syms.o scsi_sysfs.o \
scsi_devinfo.o
-scsi_mod-$(CONFIG_PROC_FS) += scsi_proc.o
+scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o
+scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o
scsi_mod-$(CONFIG_X86_PC9800) += scsi_pc98.o
sd_mod-objs := sd.o
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index dba125a0db5c..7262cca5529e 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -2512,7 +2512,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
case HEAD_OF_QUEUE_TAG:
case ORDERED_QUEUE_TAG:
case SIMPLE_QUEUE_TAG:
- cmd->device->tagged_queue = 0;
+ cmd->device->simple_tags = 0;
hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
break;
default:
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 1ec4a55cbd10..390f63b3a371 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -6362,8 +6362,8 @@ advansys_slave_configure(Scsi_Device *device)
} else {
scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun);
}
- ASC_DBG3(1, "advansys_slave_configure: shp 0x%lx, id %d, depth %d\n",
- (ulong) shp, device->id, device->queue_depth);
+ ASC_DBG4(1, "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n",
+ (ulong) device, (ulong) boardp, device->id, device->queue_depth);
return 0;
}
@@ -9354,8 +9354,8 @@ asc_prt_scsi_host(struct Scsi_Host *s)
printk("Scsi_Host at addr 0x%lx\n", (ulong) s);
printk(
-" next 0x%lx, host_busy %u, host_no %d, last_reset %d,\n",
- (ulong) s->next, s->host_busy, s->host_no,
+" host_busy %u, host_no %d, last_reset %d,\n",
+ s->host_busy, s->host_no,
(unsigned) s->last_reset);
#if ASC_LINUX_KERNEL24
@@ -9399,8 +9399,8 @@ asc_prt_scsi_cmnd(Scsi_Cmnd *s)
printk(
" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
- (ulong) s->host, (ulong) s->device, s->target, s->lun,
- s->channel);
+ (ulong) s->device->host, (ulong) s->device, s->device->id, s->device->lun,
+ s->device->channel);
asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index a0452a6c6122..efc61b3f2502 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -768,7 +768,7 @@ intr_ret_t acornscsi_kick(AS_Host *host)
/*
* tagged queueing - allocate a new tag to this command
*/
- if (SCpnt->device->tagged_queue) {
+ if (SCpnt->device->simple_tags) {
SCpnt->device->current_tag += 1;
if (SCpnt->device->current_tag == 0)
SCpnt->device->current_tag = 1;
@@ -1590,7 +1590,7 @@ void acornscsi_message(AS_Host *host)
*/
printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
host->host->host_no, acornscsi_target(host));
- host->SCpnt->device->tagged_queue = 0;
+ host->SCpnt->device->simple_tags = 0;
set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns);
break;
#endif
@@ -2935,7 +2935,7 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
p += sprintf(p, " %d/%d ", scd->id, scd->lun);
if (scd->tagged_supported)
p += sprintf(p, "%3sabled(%3d) ",
- scd->tagged_queue ? "en" : "dis",
+ scd->simple_tags ? "en" : "dis",
scd->current_tag);
else
p += sprintf(p, "unsupported ");
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index fbda4d4f78a7..2c99ea7dae85 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -1819,7 +1819,7 @@ static void fas216_allocate_tag(FAS216_Info *info, Scsi_Cmnd *SCpnt)
/*
* tagged queuing - allocate a new tag to this command
*/
- if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE &&
+ if (SCpnt->device->simple_tags && SCpnt->cmnd[0] != REQUEST_SENSE &&
SCpnt->cmnd[0] != INQUIRY) {
SCpnt->device->current_tag += 1;
if (SCpnt->device->current_tag == 0)
@@ -3012,7 +3012,7 @@ int fas216_print_devices(FAS216_Info *info, char *buffer)
p += sprintf(p, " %d/%d ", scd->id, scd->lun);
if (scd->tagged_supported)
p += sprintf(p, "%3sabled(%3d) ",
- scd->tagged_queue ? "en" : "dis",
+ scd->simple_tags ? "en" : "dis",
scd->current_tag);
else
p += sprintf(p, "unsupported ");
diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
index 943778cca0eb..d165a3af3e14 100644
--- a/drivers/scsi/cpqfcTSinit.c
+++ b/drivers/scsi/cpqfcTSinit.c
@@ -603,7 +603,7 @@ int cpqfcTS_ioctl( struct scsi_device *ScsiDev, int Cmnd, void *arg)
return -ENOMEM;
}
// Now build a Scsi_Request to pass down...
- ScsiPassThruReq = scsi_allocate_request(ScsiDev);
+ ScsiPassThruReq = scsi_allocate_request(ScsiDev, GFP_KERNEL);
if (ScsiPassThruReq == NULL) {
kfree(buf);
return -ENOMEM;
diff --git a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c
index b41038baa394..2b5735863b65 100644
--- a/drivers/scsi/cpqfcTSworker.c
+++ b/drivers/scsi/cpqfcTSworker.c
@@ -2878,7 +2878,7 @@ static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd)
}
}
-Done:
+Done: ;
}
extern int is_private_data_of_cpqfc(CPQFCHBA *hba, void * pointer);
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index e0a1d2191eed..107c220ae086 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -224,14 +224,14 @@ static char traceoverflow[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
#define DC395x_SMP_IO_UNLOCK(dev,irq_flags) spin_unlock_irqrestore(((struct Scsi_Host*)dev)->host_lock,irq_flags)
-#define DC395x_read8(acb,address) (u8)(inb(acb->IOPortBase + (address)))
+#define DC395x_read8(acb,address) (u8)(inb(acb->io_port_base + (address)))
#define DC395x_read8_(address, base) (u8)(inb((USHORT)(base) + (address)))
-#define DC395x_read16(acb,address) (u16)(inw(acb->IOPortBase + (address)))
-#define DC395x_read32(acb,address) (u32)(inl(acb->IOPortBase + (address)))
-#define DC395x_write8(acb,address,value) outb((value), acb->IOPortBase + (address))
+#define DC395x_read16(acb,address) (u16)(inw(acb->io_port_base + (address)))
+#define DC395x_read32(acb,address) (u32)(inl(acb->io_port_base + (address)))
+#define DC395x_write8(acb,address,value) outb((value), acb->io_port_base + (address))
#define DC395x_write8_(address,value,base) outb((value), (USHORT)(base) + (address))
-#define DC395x_write16(acb,address,value) outw((value), acb->IOPortBase + (address))
-#define DC395x_write32(acb,address,value) outl((value), acb->IOPortBase + (address))
+#define DC395x_write16(acb,address,value) outw((value), acb->io_port_base + (address))
+#define DC395x_write32(acb,address,value) outl((value), acb->io_port_base + (address))
#define BUS_ADDR(sg) sg_dma_address(&(sg))
@@ -383,7 +383,8 @@ struct DeviceCtlBlk {
struct AdapterCtlBlk {
struct Scsi_Host *scsi_host;
- u16 IOPortBase;
+ u16 io_port_base;
+ u16 io_port_len;
struct list_head dcb_list; /* head of going dcb list */
struct DeviceCtlBlk *dcb_run_robin;
@@ -496,10 +497,6 @@ static void request_sense(struct AdapterCtlBlk *acb,
struct ScsiReqBlk *srb);
static inline void set_xfer_rate(struct AdapterCtlBlk *acb,
struct DeviceCtlBlk *dcb);
-static void init_dcb(struct AdapterCtlBlk *acb,
- struct DeviceCtlBlk **pdcb, u8 target, u8 lun);
-static void remove_dev(struct AdapterCtlBlk *acb,
- struct DeviceCtlBlk *dcb);
static void waiting_timeout(unsigned long ptr);
@@ -822,6 +819,7 @@ void __init eeprom_override(struct NvRamType *eeprom)
*
* @head: The pointer to the head of the list to count the items in.
**/
+static
unsigned int list_size(struct list_head *head)
{
unsigned int count = 0;
@@ -841,6 +839,7 @@ unsigned int list_size(struct list_head *head)
* @pos: The pointer the dcb for which we are searching for the
* following dcb.
**/
+static
struct DeviceCtlBlk *dcb_get_next(
struct list_head *head,
struct DeviceCtlBlk *pos)
@@ -1449,34 +1448,6 @@ complete:
}
-/***********************************************************************
- * Function static int dc395x_slave_alloc()
- *
- * Purpose: Allocate DCB
- ***********************************************************************/
-static int dc395x_slave_alloc(struct scsi_device *sdp)
-{
- struct AdapterCtlBlk *acb;
- struct DeviceCtlBlk *dummy;
-
- acb = (struct AdapterCtlBlk *) sdp->host->hostdata;
-
- init_dcb(acb, &dummy, sdp->id, sdp->lun);
-
- return dummy ? 0 : -ENOMEM;
-}
-
-
-static void dc395x_slave_destroy(struct scsi_device *sdp)
-{
- struct AdapterCtlBlk *acb;
- struct DeviceCtlBlk *dcb;
-
- acb = (struct AdapterCtlBlk *) sdp->host->hostdata;
- dcb = find_dcb(acb, sdp->id, sdp->lun);
-
- remove_dev(acb, dcb);
-}
/*
@@ -1635,7 +1606,6 @@ static void reset_dev_param(struct AdapterCtlBlk *acb)
dcb->sync_offset = 0;
dcb->dev_mode = eeprom->target[dcb->target_id].cfg0;
- /*dcb->AdpMode = eeprom->channel_cfg; */
period_index = eeprom->target[dcb->target_id].period & 0x07;
dcb->min_nego_period = clock_period[period_index];
if (!(dcb->dev_mode & NTC_DO_WIDE_NEGO)
@@ -1824,7 +1794,6 @@ static void selto_timer(struct AdapterCtlBlk *acb)
{
if (timer_pending(&acb->selto_timer))
return;
- init_timer(&acb->selto_timer);
acb->selto_timer.function = selection_timeout_missed;
acb->selto_timer.data = (unsigned long) acb;
if (time_before
@@ -4049,40 +4018,8 @@ static void reselect(struct AdapterCtlBlk *acb)
}
-/* Dynamic device handling */
-
-/* Remove dev (and DCB) */
-static
-void remove_dev(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb)
-{
- struct DeviceCtlBlk *i;
- struct DeviceCtlBlk *tmp;
-
- dprintkdbg(DBG_0, "remove_dev\n");
- if (list_size(&dcb->srb_going_list) > 1) {
- dprintkdbg(DBG_DCB, "Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",
- dcb->target_id, dcb->target_lun, (int) dcb,
- list_size(&dcb->srb_going_list));
- return;
- }
- acb->dcb_map[dcb->target_id] &= ~(1 << dcb->target_lun);
- acb->children[dcb->target_id][dcb->target_lun] = NULL;
- list_for_each_entry_safe(i, tmp, &acb->dcb_list, list) {
- if (dcb == i) {
- list_del(&i->list);
- break;
- }
- }
- dprintkdbg(DBG_DCB, "Driver about to free DCB (ID %i, LUN %i): %p\n",
- dcb->target_id, dcb->target_lun, dcb);
- if (dcb == acb->active_dcb)
- acb->active_dcb = NULL;
- if (dcb == acb->dcb_run_robin)
- acb->dcb_run_robin = dcb_get_next(&acb->dcb_list, dcb);
- dc395x_kfree(dcb);
-}
static inline u8 tagq_blacklist(char *name)
@@ -4681,58 +4618,55 @@ void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
}
-/*
- *********************************************************************
- * dc395x_queue_command
+
+
+
+/**
+ * device_alloc - Allocate a new device instance. This create the
+ * devices instance and sets up all the data items. The adapter
+ * instance is required to obtain confiuration information for this
+ * device. This does *not* add this device to the adapters device
+ * list.
*
- * Function : void init_dcb
- * Purpose : initialize the internal structures for a given DCB
- * Inputs : cmd - pointer to this scsi cmd request block structure
- *********************************************************************
- */
+ * @acb: The adapter to obtain configuration information from.
+ * @target: The target for the new device.
+ * @lun: The lun for the new device.
+ *
+ * Return the new device if succesfull or NULL on failure.
+ **/
static
-void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb,
- u8 target, u8 lun)
+struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb, u8 target, u8 lun)
{
struct NvRamType *eeprom = &acb->eeprom;
- u8 period_index;
+ u8 period_index = eeprom->target[target].period & 0x07;
struct DeviceCtlBlk *dcb;
- struct DeviceCtlBlk *dcb2;
- dprintkdbg(DBG_0, "init_dcb..............\n");
dcb = dc395x_kmalloc(sizeof(struct DeviceCtlBlk), GFP_ATOMIC);
- /*dcb = find_dcb (acb, target, lun); */
- *pdcb = dcb;
- dcb2 = NULL;
- if (!dcb)
- return;
-
- INIT_LIST_HEAD(&dcb->srb_waiting_list);
+ dprintkdbg(DBG_0, "device_alloc: device %p\n", dcb);
+ if (!dcb) {
+ return NULL;
+ }
+ dcb->acb = NULL;
INIT_LIST_HEAD(&dcb->srb_going_list);
- if (list_empty(&acb->dcb_list))
- acb->dcb_run_robin = dcb;
- list_add_tail(&dcb->list, &acb->dcb_list);
-
- /* $$$$$$$ */
- dcb->acb = acb;
- dcb->target_id = target;
- dcb->target_lun = lun;
- /* $$$$$$$ */
+ INIT_LIST_HEAD(&dcb->srb_waiting_list);
dcb->active_srb = NULL;
- /* $$$$$$$ */
dcb->tag_mask = 0;
- dcb->flag = 0;
dcb->max_command = 1;
- /* $$$$$$$ */
+ dcb->target_id = target;
+ dcb->target_lun = lun;
+#ifndef DC395x_NO_DISCONNECT
+ dcb->identify_msg =
+ IDENTIFY(dcb->dev_mode & NTC_DO_DISCONNECT, lun);
+#else
+ dcb->identify_msg = IDENTIFY(0, lun);
+#endif
dcb->dev_mode = eeprom->target[target].cfg0;
- /*dcb->AdpMode = eeprom->channel_cfg; */
dcb->inquiry7 = 0;
dcb->sync_mode = 0;
- /* $$$$$$$ */
+ dcb->min_nego_period = clock_period[period_index];
dcb->sync_period = 0;
dcb->sync_offset = 0;
- period_index = eeprom->target[target].period & 0x07;
- dcb->min_nego_period = clock_period[period_index];
+ dcb->flag = 0;
#ifndef DC395x_NO_WIDE
if ((dcb->dev_mode & NTC_DO_WIDE_NEGO)
@@ -4744,318 +4678,166 @@ void init_dcb(struct AdapterCtlBlk *acb, struct DeviceCtlBlk **pdcb,
if (!(lun) || current_sync_offset)
dcb->sync_mode |= SYNC_NEGO_ENABLE;
#endif
- /* $$$$$$$ */
-#ifndef DC395x_NO_DISCONNECT
- dcb->identify_msg =
- IDENTIFY(dcb->dev_mode & NTC_DO_DISCONNECT, lun);
-#else
- dcb->identify_msg = IDENTIFY(0, lun);
-#endif
- /* $$$$$$$ */
if (dcb->target_lun != 0) {
/* Copy settings */
- struct DeviceCtlBlk *prevDCB;
- list_for_each_entry(prevDCB, &acb->dcb_list, list)
- if (prevDCB->target_id == dcb->target_id)
+ struct DeviceCtlBlk *p;
+ list_for_each_entry(p, &acb->dcb_list, list)
+ if (p->target_id == dcb->target_id)
break;
- dprintkdbg(DBG_KG,
+ dprintkdbg(DBG_KG,
"Copy settings from %02i-%02i to %02i-%02i\n",
- prevDCB->target_id, prevDCB->target_lun,
+ p->target_id, p->target_lun,
dcb->target_id, dcb->target_lun);
- dcb->sync_mode = prevDCB->sync_mode;
- dcb->sync_period = prevDCB->sync_period;
- dcb->min_nego_period = prevDCB->min_nego_period;
- dcb->sync_offset = prevDCB->sync_offset;
- dcb->inquiry7 = prevDCB->inquiry7;
- };
-
- acb->dcb_map[target] |= (1 << lun);
- acb->children[target][lun] = dcb;
+ dcb->sync_mode = p->sync_mode;
+ dcb->sync_period = p->sync_period;
+ dcb->min_nego_period = p->min_nego_period;
+ dcb->sync_offset = p->sync_offset;
+ dcb->inquiry7 = p->inquiry7;
+ }
+ return dcb;
}
-#if debug_enabled(DBG_TRACE|DBG_TRACEALL)
-/*
- * Memory for trace buffers
- */
+/**
+ * adapter_add_device - Adds the device instance to the adaptor instance.
+ *
+ * @acb: The adapter device to be updated
+ * @dcb: A newly created and intialised device instance to add.
+ **/
static
-void free_tracebufs(struct AdapterCtlBlk *acb, int srb_idx)
+void adapter_add_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb)
{
- int i;
- const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ;
- for (i = 0; i < srb_idx; i += bufs_per_page) {
- /*dprintkl(KERN_DEBUG, "Free tracebuf %p (for %i)\n", */
- /* acb->srb_array[i].debugtrace, i); */
- dc395x_kfree(acb->srb_array[i].debugtrace);
- }
-}
+ /* backpointer to adapter */
+ dcb->acb = acb;
+
+ /* set run_robin to this device if it is currently empty */
+ if (list_empty(&acb->dcb_list))
+ acb->dcb_run_robin = dcb;
+ /* add device to list */
+ list_add_tail(&dcb->list, &acb->dcb_list);
-static
-int alloc_tracebufs(struct AdapterCtlBlk *acb)
-{
- const unsigned mem_needed =
- (DC395x_MAX_SRB_CNT + 1) * DEBUGTRACEBUFSZ;
- int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE;
- const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ;
- int srb_idx = 0;
- unsigned i = 0;
- unsigned char *ptr;
- /*dprintkl(KERN_DEBUG, "Alloc %i pages for tracebufs\n", pages); */
- while (pages--) {
- ptr = dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!ptr) {
- free_tracebufs(acb, srb_idx);
- return 1;
- }
- /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for tracebuf %i\n", */
- /* PAGE_SIZE, ptr, srb_idx); */
- i = 0;
- while (i < bufs_per_page && srb_idx < DC395x_MAX_SRB_CNT)
- acb->srb_array[srb_idx++].debugtrace =
- ptr + (i++ * DEBUGTRACEBUFSZ);
- }
- if (i < bufs_per_page) {
- acb->srb.debugtrace = ptr + (i * DEBUGTRACEBUFSZ);
- acb->srb.debugtrace[0] = 0;
- } else
- dprintkl(KERN_DEBUG, "No space for tmsrb tracebuf reserved?!\n");
- return 0;
+ /* update device maps */
+ acb->dcb_map[dcb->target_id] |= (1 << dcb->target_lun);
+ acb->children[dcb->target_id][dcb->target_lun] = dcb;
}
-#endif
-/* Free SG tables */
-static void free_sg_tables(struct AdapterCtlBlk *acb, int srb_idx)
+/**
+ * adapter_remove_device - Removes the device instance from the adaptor
+ * instance. The device instance is not check in any way or freed by this.
+ * The caller is expected to take care of that. This will simply remove the
+ * device from the adapters data strcutures.
+ *
+ * @acb: The adapter device to be updated
+ * @dcb: A device that has previously been added to the adapter.
+ **/
+static
+void adapter_remove_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb)
{
- int i;
- const unsigned srbs_per_page =
- PAGE_SIZE / (DC395x_MAX_SG_LISTENTRY * sizeof(struct SGentry));
- for (i = 0; i < srb_idx; i += srbs_per_page) {
- /*dprintkl(KERN_DEBUG, "Free SG segs %p (for %i)\n", */
- /* acb->srb_array[i].segment_x, i); */
- dc395x_kfree(acb->srb_array[i].segment_x);
- }
-}
+ struct DeviceCtlBlk *i;
+ struct DeviceCtlBlk *tmp;
+ dprintkdbg(DBG_0, "adapter_remove_device: Remove device (ID %i, LUN %i): %p\n",
+ dcb->target_id, dcb->target_lun, dcb);
+ /* fix up any pointers to this device that we have in the adapter */
+ if (acb->active_dcb == dcb)
+ acb->active_dcb = NULL;
+ if (acb->dcb_run_robin == dcb)
+ acb->dcb_run_robin = dcb_get_next(&acb->dcb_list, dcb);
-/*
- * Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*)
- * should never cross a page boundary */
-static int alloc_sg_tables(struct AdapterCtlBlk *acb)
-{
- const unsigned mem_needed =
- (DC395x_MAX_SRB_CNT +
- 1) * DC395x_MAX_SG_LISTENTRY * sizeof(struct SGentry);
- int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE;
- const unsigned srbs_per_page =
- PAGE_SIZE / (DC395x_MAX_SG_LISTENTRY * sizeof(struct SGentry));
- int srb_idx = 0;
- unsigned i = 0;
- struct SGentry *ptr;
- /*dprintkl(KERN_DEBUG, "Alloc %i pages for SG tables\n", pages); */
- while (pages--) {
- ptr = (struct SGentry *) dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!ptr) {
- free_sg_tables(acb, srb_idx);
- return 1;
+ /* unlink from list */
+ list_for_each_entry_safe(i, tmp, &acb->dcb_list, list)
+ if (dcb == i) {
+ list_del(&i->list);
+ break;
}
- /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for SG segments %i\n", */
- /* PAGE_SIZE, ptr, srb_idx); */
- i = 0;
- while (i < srbs_per_page && srb_idx < DC395x_MAX_SRB_CNT)
- acb->srb_array[srb_idx++].segment_x =
- ptr + (i++ * DC395x_MAX_SG_LISTENTRY);
- }
- if (i < srbs_per_page)
- acb->srb.segment_x =
- ptr + (i * DC395x_MAX_SG_LISTENTRY);
- else
- dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
- return 0;
+
+ /* clear map and children */
+ acb->dcb_map[dcb->target_id] &= ~(1 << dcb->target_lun);
+ acb->children[dcb->target_id][dcb->target_lun] = NULL;
+ dcb->acb = NULL;
}
-/*
- ********************************************************************
- * scsiio
- * init_acb
- ********************************************************************
+/**
+ * adapter_remove_and_free_device - Removes a single device from the adapter
+ * and then frees the device information.
+ *
+ * @acb: The adapter device to be updated
+ * @dcb: A device that has previously been added to the adapter.
*/
-static void __init link_srb(struct AdapterCtlBlk *acb)
+static
+void adapter_remove_and_free_device(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb)
{
- int i;
-
- for (i = 0; i < acb->srb_count - 1; i++)
- srb_free_insert(acb, &acb->srb_array[i]);
+ if (list_size(&dcb->srb_going_list) > 1) {
+ dprintkdbg(DBG_DCB, "adapter_remove_and_free_device: "
+ "Won't remove because of %i active requests\n",
+ list_size(&dcb->srb_going_list));
+ return;
+ }
+ adapter_remove_device(acb, dcb);
+ dc395x_kfree(dcb);
}
-/*
- ***********************************************************************
- * host_init
+/**
+ * adapter_remove_and_free_all_devices - Removes and frees all of the
+ * devices associated with the specified adapter.
*
- * Function : static void init_acb
- * Purpose : initialize the internal structures for a given SCSI host
- * Inputs : host - pointer to this host adapter's structure
- ***********************************************************************
- */
+ * @acb: The adapter from which all devices should be removed.
+ **/
static
-int __init init_acb(struct Scsi_Host *host, u32 io_port, u8 irq)
+void adapter_remove_and_free_all_devices(struct AdapterCtlBlk* acb)
{
- struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
- struct NvRamType *eeprom = &acb->eeprom;
- u16 i;
+ struct DeviceCtlBlk *dcb;
+ struct DeviceCtlBlk *tmp;
+ dprintkdbg(DBG_DCB, "adapter_remove_and_free_all_devices: Free all devices (%i devices)\n",
+ list_size(&acb->dcb_list));
- host->max_cmd_len = 24;
- host->can_queue = DC395x_MAX_CMD_QUEUE;
- host->cmd_per_lun = DC395x_MAX_CMD_PER_LUN;
- host->this_id = (int) eeprom->scsi_id;
- host->io_port = io_port;
- host->n_io_port = 0x80;
- host->dma_channel = -1;
- host->unique_id = io_port;
- host->irq = irq;
- host->last_reset = jiffies;
+ list_for_each_entry_safe(dcb, tmp, &acb->dcb_list, list)
+ adapter_remove_and_free_device(acb, dcb);
+}
- host->max_id = 16;
- if (host->max_id - 1 == eeprom->scsi_id)
- host->max_id--;
-#ifdef CONFIG_SCSI_MULTI_LUN
- if (eeprom->channel_cfg & NAC_SCANLUN)
- host->max_lun = 8;
- else
- host->max_lun = 1;
-#else
- host->max_lun = 1;
-#endif
- /*
- ********************************
- */
- acb->scsi_host = host;
- acb->IOPortBase = (u16) io_port;
- acb->dcb_run_robin = NULL;
- acb->active_dcb = NULL;
- acb->srb_count = DC395x_MAX_SRB_CNT;
- acb->scsi_host->this_id = eeprom->scsi_id;
- acb->hostid_bit = (1 << acb->scsi_host->this_id);
- /*acb->scsi_host->this_lun = 0; */
- acb->irq_level = irq;
- acb->tag_max_num = 1 << eeprom->max_tag;
- if (acb->tag_max_num > 30)
- acb->tag_max_num = 30;
- acb->acb_flag = 0; /* RESET_DETECT, RESET_DONE, RESET_DEV */
- acb->scan_devices = 1;
- acb->msg_len = 0;
- acb->gmode2 = eeprom->channel_cfg;
- if (eeprom->channel_cfg & NAC_SCANLUN)
- acb->lun_chk = 1;
- /*
- * link all device's SRB Q of this adapter
- */
- if (alloc_sg_tables(acb)) {
- dprintkl(KERN_DEBUG, "SG table allocation failed!\n");
- return 1;
- }
-#if debug_enabled(DBG_TRACE|DBG_TRACEALL)
- if (alloc_tracebufs(acb)) {
- dprintkl(KERN_DEBUG, "SG trace buffer allocation failed!\n");
- free_sg_tables(acb, DC395x_MAX_SRB_CNT);
- return 1;
- }
-#endif
- INIT_LIST_HEAD(&acb->dcb_list);
- INIT_LIST_HEAD(&acb->srb_free_list);
- link_srb(acb);
+/**
+ * dc395x_slave_alloc - Called by the scsi mid layer to tell us about a new
+ * scsi device that we need to deal with. We allocate a new device and then
+ * insert that device into the adapters device list.
+ *
+ * @scsi_device: The new scsi device that we need to handle.
+ **/
+static
+int dc395x_slave_alloc(struct scsi_device *scsi_device)
+{
+ struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)scsi_device->host->hostdata;
+ struct DeviceCtlBlk *dcb;
- /*
- * temp SRB for Q tag used or abort command used
- */
- acb->tmp_srb = &acb->srb;
- init_timer(&acb->waiting_timer);
+ dcb = device_alloc(acb, scsi_device->id, scsi_device->lun);
+ if (!dcb)
+ return -ENOMEM;
+ adapter_add_device(acb, dcb);
- for (i = 0; i < DC395x_MAX_SCSI_ID; i++)
- acb->dcb_map[i] = 0;
- dprintkdbg(DBG_0, "acb = %p, pdcb_map = %p, psrb_array = %p\n", acb,
- acb->dcb_map, acb->srb_array);
- dprintkdbg(DBG_0, "ACB size= %04x, DCB size= %04x, SRB size= %04x\n",
- sizeof(struct AdapterCtlBlk), sizeof(struct DeviceCtlBlk),
- sizeof(struct ScsiReqBlk));
return 0;
}
-/*===========================================================================
- Init
- ===========================================================================*/
/**
- * init_adapter - Initialize the SCSI chip control registers
- *
- * @host: This hosts adapter strcuture
- * @io_port: The base I/O port
- * @irq: IRQ
+ * dc395x_slave_destroy - Called by the scsi mid layer to tell us about a
+ * device that is going away.
*
- * Returns 0 if the initialization succeeds, any other value on failure.
+ * @scsi_device: The new scsi device that we need to handle.
**/
static
-int __init init_adapter(struct Scsi_Host *host, u32 io_port, u8 irq)
+void dc395x_slave_destroy(struct scsi_device *scsi_device)
{
- struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
- struct NvRamType *eeprom = &acb->eeprom;
-
- if (!request_region(io_port, host->n_io_port, DC395X_NAME)) {
- dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port);
- return -1;
- }
- if (request_irq(irq, dc395x_interrupt, SA_SHIRQ, DC395X_NAME, acb)) {
- /* release the region we just claimed */
- release_region(io_port, host->n_io_port);
- dprintkl(KERN_INFO, "Failed to register IRQ!\n");
- return -1;
- }
-
- acb->IOPortBase = io_port;
-
- /* selection timeout = 250 ms */
- acb->sel_timeout = DC395x_SEL_TIMEOUT;
-
- /* Mask all the interrupt */
- DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0x00);
- DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0x00);
-
- /* Reset SCSI module */
- DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_RSTMODULE);
-
- /* Reset PCI/DMA module */
- DC395x_write8(acb, TRM_S1040_DMA_CONTROL, DMARESETMODULE);
- udelay(20);
-
- /* program configuration 0 */
- acb->config = HCC_AUTOTERM | HCC_PARITY;
- if (DC395x_read8(acb, TRM_S1040_GEN_STATUS) & WIDESCSI)
- acb->config |= HCC_WIDE_CARD;
-
- if (eeprom->channel_cfg & NAC_POWERON_SCSI_RESET)
- acb->config |= HCC_SCSI_RESET;
-
- if (acb->config & HCC_SCSI_RESET) {
- dprintkl(KERN_INFO, "Performing initial SCSI bus reset\n");
- DC395x_write8(acb, TRM_S1040_SCSI_CONTROL, DO_RSTSCSI);
-
- /*while (!( DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS) & INT_SCSIRESET )); */
- /*spin_unlock_irq (&io_request_lock); */
- udelay(500);
+ struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)scsi_device->host->hostdata;
+ struct DeviceCtlBlk *dcb = find_dcb(acb, scsi_device->id, scsi_device->lun);
+ if (dcb)
+ adapter_remove_and_free_device(acb, dcb);
+}
- acb->scsi_host->last_reset =
- jiffies + HZ / 2 +
- HZ * acb->eeprom.delay_time;
- /*spin_lock_irq (&io_request_lock); */
- }
- set_basic_config(acb);
- return 0;
-}
/**
@@ -5363,20 +5145,161 @@ void __init check_eeprom(struct NvRamType *eeprom, u16 io_port)
}
+
+
/**
- * print_config - print adapter connection and termination
+ * print_eeprom_settings - output the eeprom settings
+ * to the kernel log so people can see what they were.
+ *
+ * @eeprom: The eeprom data strucutre to show details for.
+ **/
+static
+void __init print_eeprom_settings(struct NvRamType *eeprom)
+{
+ dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n",
+ eeprom->scsi_id,
+ eeprom->target[0].period,
+ clock_speed[eeprom->target[0].period] / 10,
+ clock_speed[eeprom->target[0].period] % 10,
+ eeprom->target[0].cfg0);
+ dprintkl(KERN_INFO, " AdaptMode=0x%02x, Tags=%i(%02i), DelayReset=%is\n",
+ eeprom->channel_cfg,
+ eeprom->max_tag,
+ 1 << eeprom->max_tag,
+ eeprom->delay_time);
+}
+
+
+
+#if debug_enabled(DBG_TRACE|DBG_TRACEALL)
+/*
+ * Memory for trace buffers
+ */
+static
+void free_tracebufs(struct AdapterCtlBlk *acb)
+{
+ int i;
+ const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ;
+
+ for (i = 0; i < srb_idx; i += bufs_per_page)
+ if (acb->srb_array[i].debugtrace)
+ dc395x_kfree(acb->srb_array[i].debugtrace);
+}
+
+
+static
+int alloc_tracebufs(struct AdapterCtlBlk *acb)
+{
+ const unsigned mem_needed =
+ (DC395x_MAX_SRB_CNT + 1) * DEBUGTRACEBUFSZ;
+ int pages = (mem_needed + (PAGE_SIZE - 1)) / PAGE_SIZE;
+ const unsigned bufs_per_page = PAGE_SIZE / DEBUGTRACEBUFSZ;
+ int srb_idx = 0;
+ unsigned i = 0;
+ unsigned char *ptr;
+
+ for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
+ acb->srb_array[i].debugtrace = NULL;
+
+ while (pages--) {
+ ptr = dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!ptr) {
+ free_tracebufs(acb);
+ return 1;
+ }
+ /*dprintkl(KERN_DEBUG, "Alloc %li bytes at %p for tracebuf %i\n", */
+ /* PAGE_SIZE, ptr, srb_idx); */
+ i = 0;
+ while (i < bufs_per_page && srb_idx < DC395x_MAX_SRB_CNT)
+ acb->srb_array[srb_idx++].debugtrace =
+ ptr + (i++ * DEBUGTRACEBUFSZ);
+ }
+ if (i < bufs_per_page) {
+ acb->srb.debugtrace = ptr + (i * DEBUGTRACEBUFSZ);
+ acb->srb.debugtrace[0] = 0;
+ } else
+ dprintkl(KERN_DEBUG, "No space for tmsrb tracebuf reserved?!\n");
+ return 0;
+}
+#else
+static void free_tracebufs(struct AdapterCtlBlk *acb) {}
+static int alloc_tracebufs(struct AdapterCtlBlk *acb) { return 0; }
+#endif
+
+/* Free SG tables */
+static
+void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
+{
+ int i;
+ const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY
+ *sizeof(struct SGentry));
+
+ for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
+ if (acb->srb_array[i].segment_x)
+ dc395x_kfree(acb->srb_array[i].segment_x);
+}
+
+
+/*
+ * Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*)
+ * should never cross a page boundary */
+static
+int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
+{
+ const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1)
+ *DC395x_MAX_SG_LISTENTRY
+ *sizeof(struct SGentry);
+ int pages = (mem_needed+(PAGE_SIZE-1))/PAGE_SIZE;
+ const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY
+ *sizeof(struct SGentry));
+ int srb_idx = 0;
+ unsigned i = 0;
+ struct SGentry *ptr;
+
+ for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
+ acb->srb_array[i].segment_x = NULL;
+
+ dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
+ while (pages--) {
+ ptr = (struct SGentry *)dc395x_kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!ptr) {
+ adapter_sg_tables_free(acb);
+ return 1;
+ }
+ dprintkdbg(DBG_1, "Allocate %li bytes at %p for SG segments %i\n",
+ PAGE_SIZE, ptr, srb_idx);
+ i = 0;
+ while (i < srbs_per_page && srb_idx < DC395x_MAX_SRB_CNT)
+ acb->srb_array[srb_idx++].segment_x =
+ ptr + (i++ * DC395x_MAX_SG_LISTENTRY);
+ }
+ if (i < srbs_per_page)
+ acb->srb.segment_x =
+ ptr + (i * DC395x_MAX_SG_LISTENTRY);
+ else
+ dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
+ return 0;
+}
+
+
+
+/**
+ * adapter_print_config - print adapter connection and termination
* config
*
- * @acb: adapter control block
+ * The io port in the adapter needs to have been set before calling
+ * this function.
+ *
+ * @acb: The adapter to print the information for.
**/
static
-void __init print_config(struct AdapterCtlBlk *acb)
+void __init adapter_print_config(struct AdapterCtlBlk *acb)
{
u8 bval;
bval = DC395x_read8(acb, TRM_S1040_GEN_STATUS);
- dprintkl(KERN_INFO, "%c: Connectors: ",
- ((bval & WIDESCSI) ? 'W' : ' '));
+ dprintkl(KERN_INFO, "%s Connectors: ",
+ ((bval & WIDESCSI) ? "(Wide)" : ""));
if (!(bval & CON5068))
printk("ext%s ", !(bval & EXT68HIGH) ? "68" : "50");
if (!(bval & CON68))
@@ -5403,77 +5326,290 @@ void __init print_config(struct AdapterCtlBlk *acb)
/**
- * print_eeprom_settings - output the eeprom settings
- * to the kernel log so people can see what they were.
+ * adapter_init_params - Initialize the various parameters in the
+ * adapter structure. Note that the pointer to the scsi_host is set
+ * early (when this instance is created) and the io_port and irq
+ * values are set later after they have been reserved. This just gets
+ * everything set to a good starting position.
*
- * @eeprom: The eeprom data strucutre to show details for.
+ * The eeprom structure in the adapter needs to have been set before
+ * calling this function.
+ *
+ * @acb: The adapter to initialize.
**/
static
-void __init print_eeprom_settings(struct NvRamType *eeprom)
+void __init adapter_init_params(struct AdapterCtlBlk *acb)
{
- dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n",
- eeprom->scsi_id,
- eeprom->target[0].period,
- clock_speed[eeprom->target[0].period] / 10,
- clock_speed[eeprom->target[0].period] % 10,
- eeprom->target[0].cfg0);
- dprintkl(KERN_INFO, " AdaptMode=0x%02x, Tags=%i(%02i), DelayReset=%is\n",
- eeprom->channel_cfg,
- eeprom->max_tag,
- 1 << eeprom->max_tag,
- eeprom->delay_time);
+ struct NvRamType *eeprom = &acb->eeprom;
+ int i;
+
+ /* NOTE: acb->scsi_host is set at scsi_host/acb creation time */
+ /* NOTE: acb->io_port_base is set at port registration time */
+ /* NOTE: acb->io_port_len is set at port registration time */
+
+ INIT_LIST_HEAD(&acb->dcb_list);
+ acb->dcb_run_robin = NULL;
+ acb->active_dcb = NULL;
+
+ INIT_LIST_HEAD(&acb->srb_free_list);
+ /* temp SRB for Q tag used or abort command used */
+ acb->tmp_srb = &acb->srb;
+ init_timer(&acb->waiting_timer);
+ init_timer(&acb->selto_timer);
+
+ acb->srb_count = DC395x_MAX_SRB_CNT;
+
+ acb->sel_timeout = DC395x_SEL_TIMEOUT; /* timeout=250ms */
+ /* NOTE: acb->irq_level is set at IRQ registration time */
+
+ acb->tag_max_num = 1 << eeprom->max_tag;
+ if (acb->tag_max_num > 30)
+ acb->tag_max_num = 30;
+
+ acb->acb_flag = 0; /* RESET_DETECT, RESET_DONE, RESET_DEV */
+ acb->gmode2 = eeprom->channel_cfg;
+ acb->config = 0; /* NOTE: actually set in adapter_init_chip */
+
+ if (eeprom->channel_cfg & NAC_SCANLUN)
+ acb->lun_chk = 1;
+ acb->scan_devices = 1;
+
+ acb->scsi_host->this_id = eeprom->scsi_id;
+ acb->hostid_bit = (1 << acb->scsi_host->this_id);
+
+ for (i = 0; i < DC395x_MAX_SCSI_ID; i++)
+ acb->dcb_map[i] = 0;
+
+ acb->msg_len = 0;
+
+ /* link static array of srbs into the srb free list */
+ for (i = 0; i < acb->srb_count - 1; i++)
+ srb_free_insert(acb, &acb->srb_array[i]);
}
-/*
- *********************************************************************
- * DC395x_detect
+/**
+ * adapter_init_host - Initialize the scsi host instance based on
+ * values that we have already stored in the adapter instance. There's
+ * some mention that a lot of these are deprecated, so we won't use
+ * them (we'll use the ones in the adapter instance) but we'll fill
+ * them in in case something else needs them.
*
- * Function : static int host_init (struct Scsi_Host *host)
- * Purpose : initialize the internal structures for a given SCSI host
- * Inputs : host - pointer to this host adapter's structure/
- * Preconditions : when this function is called, the chip_type
- * field of the acb structure MUST have been set.
- *********************************************************************
- */
+ * The eeprom structure, irq and io ports in the adapter need to have
+ * been set before calling this function.
+ *
+ * @host: The scsi host instance to fill in the values for.
+ **/
static
-struct Scsi_Host *__init host_init(Scsi_Host_Template * host_template,
- u32 io_port, u8 irq)
+void __init adapter_init_scsi_host(struct Scsi_Host *host)
{
- struct Scsi_Host *host;
- struct AdapterCtlBlk *acb;
+ struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
+ struct NvRamType *eeprom = &acb->eeprom;
+
+ host->max_cmd_len = 24;
+ host->can_queue = DC395x_MAX_CMD_QUEUE;
+ host->cmd_per_lun = DC395x_MAX_CMD_PER_LUN;
+ host->this_id = (int)eeprom->scsi_id;
+ host->io_port = acb->io_port_base;
+ host->n_io_port = acb->io_port_len;
+ host->dma_channel = -1;
+ host->unique_id = acb->io_port_base;
+ host->irq = acb->irq_level;
+ host->last_reset = jiffies;
- host = scsi_host_alloc(host_template, sizeof(struct AdapterCtlBlk));
- if (!host) {
- dprintkl(KERN_INFO, "scsi_host_alloc failed\n");
+ host->max_id = 16;
+ if (host->max_id - 1 == eeprom->scsi_id)
+ host->max_id--;
+
+#ifdef CONFIG_SCSI_MULTI_LUN
+ if (eeprom->channel_cfg & NAC_SCANLUN)
+ host->max_lun = 8;
+ else
+ host->max_lun = 1;
+#else
+ host->max_lun = 1;
+#endif
+
+}
+
+
+/**
+ * adapter_init_chip - Get the chip into a know state and figure out
+ * some of the settings that apply to this adapter.
+ *
+ * The io port in the adapter needs to have been set before calling
+ * this function. The config will be configured correctly on return.
+ *
+ * @acb: The adapter which we are to init.
+ **/
+void __init adapter_init_chip(struct AdapterCtlBlk *acb)
+{
+ struct NvRamType *eeprom = &acb->eeprom;
+
+ /* Mask all the interrupt */
+ DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0x00);
+ DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0x00);
+
+ /* Reset SCSI module */
+ DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_RSTMODULE);
+
+ /* Reset PCI/DMA module */
+ DC395x_write8(acb, TRM_S1040_DMA_CONTROL, DMARESETMODULE);
+ udelay(20);
+
+ /* program configuration 0 */
+ acb->config = HCC_AUTOTERM | HCC_PARITY;
+ if (DC395x_read8(acb, TRM_S1040_GEN_STATUS) & WIDESCSI)
+ acb->config |= HCC_WIDE_CARD;
+
+ if (eeprom->channel_cfg & NAC_POWERON_SCSI_RESET)
+ acb->config |= HCC_SCSI_RESET;
+
+ if (acb->config & HCC_SCSI_RESET) {
+ dprintkl(KERN_INFO, "Performing initial SCSI bus reset\n");
+ DC395x_write8(acb, TRM_S1040_SCSI_CONTROL, DO_RSTSCSI);
+
+ /*while (!( DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS) & INT_SCSIRESET )); */
+ /*spin_unlock_irq (&io_request_lock); */
+ udelay(500);
+
+ acb->scsi_host->last_reset =
+ jiffies + HZ / 2 +
+ HZ * acb->eeprom.delay_time;
+
+ /*spin_lock_irq (&io_request_lock); */
+ }
+}
+
+
+/**
+ * init_adapter - Grab the resource for the card, setup the adapter
+ * information, set the card into a known state, create the various
+ * tables etc etc. This basically gets all adapter information all up
+ * to date, intialised and gets the chip in sync with it.
+ *
+ * @host: This hosts adapter structure
+ * @io_port: The base I/O port
+ * @irq: IRQ
+ *
+ * Returns 0 if the initialization succeeds, any other value on
+ * failure.
+ **/
+static
+int __init adapter_init(struct AdapterCtlBlk *acb, u32 io_port, u32 io_port_len, u8 irq)
+{
+ if (!request_region(io_port, io_port_len, DC395X_NAME)) {
+ dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port);
goto failed;
}
- acb = (struct AdapterCtlBlk *)host->hostdata;
+ /* store port base to indicate we have registered it */
+ acb->io_port_base = io_port;
+ acb->io_port_len = io_port_len;
+
+ if (request_irq(irq, dc395x_interrupt, SA_SHIRQ, DC395X_NAME, acb)) {
+ /* release the region we just claimed */
+ dprintkl(KERN_INFO, "Failed to register IRQ\n");
+ goto failed;
+ }
+ /* store irq to indicate we have registered it */
+ acb->irq_level = irq;
+ /* get eeprom configuration information and command line settings etc */
check_eeprom(&acb->eeprom, (u16)io_port);
print_eeprom_settings(&acb->eeprom);
- if (init_acb(host, io_port, irq)) {
+ /* setup adapter control block */
+ adapter_init_params(acb);
+
+ /* display card connectors/termination settings */
+ adapter_print_config(acb);
+
+ if (adapter_sg_tables_alloc(acb)) {
+ dprintkl(KERN_DEBUG, "Memory allocation for SG tables failed\n");
goto failed;
}
- print_config(acb);
-
- if (init_adapter(host, io_port, irq)) {
- dprintkl(KERN_INFO, "DC395x_initAdapter initial ERROR\n");
+ if (alloc_tracebufs(acb)) {
+ dprintkl(KERN_DEBUG, "Memory allocation for trace buffers failed\n");
goto failed;
}
+ adapter_init_scsi_host(acb->scsi_host);
+ adapter_init_chip(acb);
+ set_basic_config(acb);
- return host;
+ dprintkdbg(DBG_0, "adapter_init: acb=%p, pdcb_map=%p "
+ "psrb_array=%p ACB size=%04x, DCB size=%04x "
+ "SRB size=%04x\n",
+ acb, acb->dcb_map, acb->srb_array, sizeof(struct AdapterCtlBlk),
+ sizeof(struct DeviceCtlBlk), sizeof(struct ScsiReqBlk));
+ return 0;
failed:
- if (host)
- scsi_host_put(host);
- return NULL;
+ if (acb->irq_level)
+ free_irq(acb->irq_level, acb);
+ if (acb->io_port_base)
+ release_region(acb->io_port_base, acb->io_port_len);
+ adapter_sg_tables_free(acb);
+ free_tracebufs(acb);
+
+ return 1;
}
-#undef SEARCH
-#undef YESNO
-#undef SCANF
+
+/**
+ * adapter_uninit_chip - cleanly shut down the scsi controller chip,
+ * stopping all operations and disabling interrupt generation on the
+ * card.
+ *
+ * @acb: The adapter which we are to shutdown.
+ **/
+static
+void adapter_uninit_chip(struct AdapterCtlBlk *acb)
+{
+ /* disable interrupts */
+ DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0);
+ DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0);
+
+ /* reset the scsi bus */
+ if (acb->config & HCC_SCSI_RESET)
+ reset_scsi_bus(acb);
+
+ /* clear any pending interupt state */
+ DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS);
+}
+
+
+
+/**
+ * adapter_uninit - Shut down the chip and release any resources that
+ * we had allocated. Once this returns the adapter should not be used
+ * anymore.
+ *
+ * @acb: The adapter which we are to un-initialize.
+ **/
+static
+void adapter_uninit(struct AdapterCtlBlk *acb)
+{
+ unsigned long flags;
+ DC395x_LOCK_IO(acb->scsi_host, flags);
+
+ /* remove timers */
+ if (timer_pending(&acb->waiting_timer))
+ del_timer(&acb->waiting_timer);
+ if (timer_pending(&acb->selto_timer))
+ del_timer(&acb->selto_timer);
+
+ adapter_uninit_chip(acb);
+ adapter_remove_and_free_all_devices(acb);
+ DC395x_UNLOCK_IO(acb->scsi_host, flags);
+
+ if (acb->irq_level)
+ free_irq(acb->irq_level, acb);
+ if (acb->io_port_base)
+ release_region(acb->io_port_base, acb->io_port_len);
+
+ adapter_sg_tables_free(acb);
+ free_tracebufs(acb);
+}
/*
@@ -5500,6 +5636,7 @@ failed:
#undef SPRINTF
#define SPRINTF(args...) pos += sprintf(pos, args)
+#undef YESNO
#define YESNO(YN) \
if (YN) SPRINTF(" Yes ");\
else SPRINTF(" No ")
@@ -5526,7 +5663,7 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o
SPRINTF("SCSI Host Nr %i, ", host->host_no);
SPRINTF("DC395U/UW/F DC315/U %s\n",
(acb->config & HCC_WIDE_CARD) ? "Wide" : "");
- SPRINTF("IOPortBase 0x%04x, ", acb->IOPortBase);
+ SPRINTF("io_port_base 0x%04x, ", acb->io_port_base);
SPRINTF("irq_level 0x%02x, ", acb->irq_level);
SPRINTF(" SelTimeout %ims\n", (1638 * acb->sel_timeout) / 1000);
@@ -5633,84 +5770,6 @@ int dc395x_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t o
}
-/**
- * chip_shutdown - cleanly shut down the scsi controller chip,
- * stopping all operations and disablig interrupt generation on the
- * card.
- *
- * @acb: The scsi adapter control block of the adapter to shut down.
- **/
-static
-void chip_shutdown(struct AdapterCtlBlk *acb)
-{
- /* disable interrupt */
- DC395x_write8(acb, TRM_S1040_DMA_INTEN, 0);
- DC395x_write8(acb, TRM_S1040_SCSI_INTEN, 0);
-
- /* remove timers */
- if (timer_pending(&acb->waiting_timer))
- del_timer(&acb->waiting_timer);
- if (timer_pending(&acb->selto_timer))
- del_timer(&acb->selto_timer);
-
- /* reset the scsi bus */
- if (acb->config & HCC_SCSI_RESET)
- reset_scsi_bus(acb);
-
- /* clear any pending interupt state */
- DC395x_read8(acb, TRM_S1040_SCSI_INTSTATUS);
-
- /* release chip resources */
-#if debug_enabled(DBG_TRACE|DBG_TRACEALL)
- free_tracebufs(acb, DC395x_MAX_SRB_CNT);
-#endif
- free_sg_tables(acb, DC395x_MAX_SRB_CNT);
-}
-
-
-/**
- * free_dcbs - Free all of the DCBs.
- *
- * @acb: Adapter to remove the DCBs for.
- **/
-static
-void free_dcbs(struct AdapterCtlBlk* acb)
-{
- struct DeviceCtlBlk *dcb;
- struct DeviceCtlBlk *tmp;
-
- dprintkdbg(DBG_DCB, "Free %i DCBs\n", list_size(&acb->dcb_list));
-
- list_for_each_entry_safe(dcb, tmp, &acb->dcb_list, list) {
- dprintkdbg(DBG_DCB, "Free DCB (ID %i, LUN %i): %p\n",
- dcb->target_id, dcb->target_lun, dcb);
- remove_dev(acb, dcb);
- }
-}
-
-/**
- * host_release - shutdown device and release resources that were
- * allocate for it. Called once for each card as it is shutdown.
- *
- * @host: The adapter instance to shutdown.
- **/
-static
-void host_release(struct Scsi_Host *host)
-{
- struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)(host->hostdata);
- unsigned long flags;
-
- dprintkl(KERN_DEBUG, "DC395x release\n");
-
- DC395x_LOCK_IO(acb->scsi_host, flags);
- chip_shutdown(acb);
- free_dcbs(acb);
-
- free_irq(host->irq, acb);
- release_region(host->io_port, host->n_io_port);
-
- DC395x_UNLOCK_IO(acb->scsi_host, flags);
-}
/*
@@ -5737,6 +5796,22 @@ static Scsi_Host_Template dc395x_driver_template = {
/**
+ * banner_display - Display banner on first instance of driver
+ * initialized.
+ **/
+static
+void banner_display(void)
+{
+ static int banner_done = 0;
+ if (!banner_done)
+ {
+ dprintkl(KERN_INFO, "%s %s\n", DC395X_BANNER, DC395X_VERSION);
+ banner_done = 1;
+ }
+}
+
+
+/**
* dc395x_init_one - Initialise a single instance of the adapter.
*
* The PCI layer will call this once for each instance of the adapter
@@ -5753,51 +5828,55 @@ static
int __devinit dc395x_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
- unsigned int io_port;
- u8 irq;
struct Scsi_Host *scsi_host;
- static int banner_done = 0;
- int error = 0;
-
- dprintkdbg(DBG_0, "Init one instance of the dc395x\n");
- if (!banner_done)
- {
- dprintkl(KERN_INFO, "%s %s\n", DC395X_BANNER, DC395X_VERSION);
- banner_done = 1;
- }
+ struct AdapterCtlBlk *acb;
+ unsigned int io_port_base;
+ unsigned int io_port_len;
+ u8 irq;
+
+ dprintkdbg(DBG_0, "Init one instance (%s)\n", pci_name(dev));
+ banner_display();
if (pci_enable_device(dev))
{
dprintkl(KERN_INFO, "PCI Enable device failed.\n");
return -ENODEV;
}
-
- dprintkdbg(DBG_0, "Get resources...\n");
- io_port = pci_resource_start(dev, 0) & PCI_BASE_ADDRESS_IO_MASK;
+ io_port_base = pci_resource_start(dev, 0) & PCI_BASE_ADDRESS_IO_MASK;
+ io_port_len = pci_resource_len(dev, 0);
irq = dev->irq;
- dprintkdbg(DBG_0, "IO_PORT=%04x,IRQ=%x\n", (unsigned int) io_port, irq);
+ dprintkdbg(DBG_0, "IO_PORT=%04x, IRQ=%x\n", io_port_base, dev->irq);
- scsi_host = host_init(&dc395x_driver_template, io_port, irq);
- if (!scsi_host)
- {
- dprintkdbg(DBG_0, "host_init failed\n");
+ /* allocate scsi host information (includes out adapter) */
+ scsi_host = scsi_host_alloc(&dc395x_driver_template,
+ sizeof(struct AdapterCtlBlk));
+ if (!scsi_host) {
+ dprintkl(KERN_INFO, "scsi_host_alloc failed\n");
return -ENOMEM;
}
- ((struct AdapterCtlBlk *)(scsi_host->hostdata))->dev = dev;
+ acb = (struct AdapterCtlBlk*)scsi_host->hostdata;
+ acb->scsi_host = scsi_host;
+
+ /* initialise the adapter and everything we need */
+ if (adapter_init(acb, io_port_base, io_port_len, irq)) {
+ dprintkl(KERN_INFO, "DC395x_initAdapter initial ERROR\n");
+ scsi_host_put(scsi_host);
+ return -ENODEV;
+ }
+
pci_set_master(dev);
- pci_set_drvdata(dev, scsi_host);
/* get the scsi mid level to scan for new devices on the bus */
- error = scsi_add_host(scsi_host, &dev->dev);
- if (error) {
+ if (scsi_add_host(scsi_host, &dev->dev)) {
dprintkl(KERN_ERR, "scsi_add_host failed\n");
- error = -ENODEV;
- host_release(scsi_host);
+ adapter_uninit(acb);
scsi_host_put(scsi_host);
- } else
- scsi_scan_host(scsi_host);
+ return -ENODEV;
+ }
+ pci_set_drvdata(dev, scsi_host);
+ scsi_scan_host(scsi_host);
- return error;
+ return 0;
}
@@ -5809,16 +5888,14 @@ int __devinit dc395x_init_one(struct pci_dev *dev,
**/
static void __devexit dc395x_remove_one(struct pci_dev *dev)
{
- struct Scsi_Host *host = pci_get_drvdata(dev);
+ struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
+ struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)(scsi_host->hostdata);
dprintkdbg(DBG_0, "Removing instance\n");
- if (!host) {
- dprintkl(KERN_ERR, "no host allocated\n");
- return;
- }
- scsi_remove_host(host);
- host_release(host);
- scsi_host_put(host);
+
+ scsi_remove_host(scsi_host);
+ adapter_uninit(acb);
+ scsi_host_put(scsi_host);
pci_set_drvdata(dev, NULL);
}
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 19b77daaf4ee..6ffd2df205b6 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4990,7 +4990,7 @@ static int ioc_resetdrv(unsigned long arg, char *cmnd)
cmd.u.cache.DeviceNo = res.number;
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
- srp = scsi_allocate_request(sdev);
+ srp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!srp)
return -ENOMEM;
srp->sr_cmd_len = 12;
@@ -5091,7 +5091,7 @@ static int ioc_general(unsigned long arg, char *cmnd)
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
- srp = scsi_allocate_request(sdev);
+ srp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!srp)
return -ENOMEM;
srp->sr_cmd_len = 12;
@@ -5164,7 +5164,7 @@ static int ioc_hdrlist(unsigned long arg, char *cmnd)
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
- srp = scsi_allocate_request(sdev);
+ srp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!srp)
return -ENOMEM;
srp->sr_cmd_len = 12;
@@ -5253,7 +5253,7 @@ static int ioc_rescan(unsigned long arg, char *cmnd)
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
- srp = scsi_allocate_request(sdev);
+ srp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!srp)
return -ENOMEM;
srp->sr_cmd_len = 12;
@@ -5631,7 +5631,7 @@ static void gdth_flush(int hanum)
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
- srp = scsi_allocate_request(sdev);
+ srp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!srp)
return;
srp->sr_cmd_len = 12;
@@ -5727,7 +5727,7 @@ void gdth_halt(void)
TRACE2(("gdth_halt(): reset controller %d\n", hanum));
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
- srp = scsi_allocate_request(sdev);
+ srp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!srp) {
#if LINUX_VERSION_CODE >= 0x020100
unregister_reboot_notifier(&gdth_notifier);
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index 9c4485b2fd1c..ef67f26855fd 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -44,7 +44,7 @@ static int gdth_set_info(char *buffer,int length,int hanum,int busnum)
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
- scp = scsi_allocate_request(sdev);
+ scp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!scp)
return -ENOMEM;
scp->sr_cmd_len = 12;
@@ -797,7 +797,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
#if LINUX_VERSION_CODE >= 0x020503
sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
- scp = scsi_allocate_request(sdev);
+ scp = scsi_allocate_request(sdev, GFP_KERNEL);
if (!scp)
return -ENOMEM;
scp->sr_cmd_len = 12;
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index b270dac4e2d2..b631105fbdb2 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -627,7 +627,6 @@ static ide_driver_t idescsi_driver = {
.version = IDESCSI_VERSION,
.media = ide_scsi,
.busy = 0,
- .supports_dma = 1,
.supports_dsc_overlap = 0,
.attach = idescsi_attach,
.cleanup = idescsi_cleanup,
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 3c8377c3aa48..bcee9b28fbfe 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -86,6 +86,7 @@ int imm_release(struct Scsi_Host *host)
int host_no = host->unique_id;
printk("Releasing imm%i\n", host_no);
+ scsi_unregister(host);
parport_unregister_device(imm_hosts[host_no].dev);
return 0;
}
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 46b0069406e9..7213e6263642 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -199,7 +199,7 @@ MODULE_PARM(ips, "s");
#define IPS_VERSION_LOW ".90-BETA"
#if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
-#error "This driver has only been tested on the x86/ia64/x86_64 platforms"
+#warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
@@ -284,9 +284,9 @@ IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table */
/* This table describes all ServeRAID Adapters */
static struct pci_device_id ips_pci_table[] = {
{ 0x1014, 0x002E, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
- { 0x1014, 0x01BD, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
- { 0x9005, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
- { 0, }
+ { 0x1014, 0x01BD, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+ { 0x9005, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+ { 0, }
};
MODULE_DEVICE_TABLE( pci, ips_pci_table );
@@ -300,7 +300,7 @@ struct pci_driver ips_pci_driver = {
.name = ips_hot_plug_name,
.id_table = ips_pci_table,
.probe = ips_insert_device,
- .remove = __devexit_p(ips_remove_device),
+ .remove = __devexit_p(ips_remove_device),
};
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index f0e8d85e6500..4fa1a9955ddf 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -4357,19 +4357,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
}
cp->cmd = cmd;
- /*---------------------------------------------------
- **
- ** Enable tagged queue if asked by scsi ioctl
- **
- **----------------------------------------------------
- */
-#if 0 /* This stuff was only useful for linux-1.2.13 */
- if (lp && !lp->numtags && cmd->device && cmd->device->tagged_queue) {
- lp->numtags = tp->usrtags;
- ncr_setup_tags (np, cmd->device->id, cmd->device->lun);
- }
-#endif
-
/*----------------------------------------------------
**
** Build the identify / tag / sdtr message
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 48afbdd2faa8..c6bfb85db04b 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -316,7 +316,7 @@ static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
static int repeat = 0;
#endif
if (SRpnt == NULL) {
- if ((SRpnt = scsi_allocate_request(STp->device)) == NULL) {
+ if ((SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC)) == NULL) {
printk(KERN_ERR "%s:E: Can't get SCSI request.\n", tape_name(STp));
if (signal_pending(current))
(STp->buffer)->syscall_result = (-EINTR);
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index f8ebdb8bbfc4..5de0a6329d8a 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -3655,7 +3655,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
/* Enable simple tag queuing if device supports it. */
- if (cmd->device->tagged_queue)
+ if (cmd->device->simple_tags)
pkt->control_flags |= cpu_to_le16(BIT_3);
/* Load SCSI command packet. */
@@ -3955,7 +3955,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
/* Enable simple tag queuing if device supports it. */
- if (cmd->device->tagged_queue)
+ if (cmd->device->simple_tags)
pkt->control_flags |= cpu_to_le16(BIT_3);
/* Load SCSI command packet. */
@@ -4915,7 +4915,7 @@ qla12160_get_target_parameters(struct scsi_qla_host *ha, Scsi_Device *device)
} else
printk(" Async");
- if (device->tagged_queue)
+ if (device->simple_tags)
printk(", Tagged queuing: depth %d", device->queue_depth);
printk("\n");
}
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index d5894886fcea..cda15b271b21 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -113,26 +113,21 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = {
*
* Purpose: Allocate a request descriptor.
*
- * Arguments: device - device for which we want a request
+ * Arguments: device - device for which we want a request
+ * gfp_mask - allocation flags passed to kmalloc
*
* Lock status: No locks assumed to be held. This function is SMP-safe.
*
* Returns: Pointer to request block.
- *
- * Notes: With the new queueing code, it becomes important
- * to track the difference between a command and a
- * request. A request is a pending item in the queue that
- * has not yet reached the top of the queue.
- *
- * XXX(hch): Need to add a gfp_mask argument.
*/
-struct scsi_request *scsi_allocate_request(struct scsi_device *sdev)
+struct scsi_request *scsi_allocate_request(struct scsi_device *sdev,
+ int gfp_mask)
{
const int offset = ALIGN(sizeof(struct scsi_request), 4);
const int size = offset + sizeof(struct request);
struct scsi_request *sreq;
- sreq = kmalloc(size, GFP_ATOMIC);
+ sreq = kmalloc(size, gfp_mask);
if (likely(sreq != NULL)) {
memset(sreq, 0, size);
sreq->sr_request = (struct request *)(((char *)sreq) + offset);
@@ -1006,9 +1001,12 @@ static int __init init_scsi(void)
error = scsi_init_hosts();
if (error)
goto cleanup_devlist;
- error = scsi_sysfs_register();
+ error = scsi_init_sysctl();
if (error)
goto cleanup_hosts;
+ error = scsi_sysfs_register();
+ if (error)
+ goto cleanup_sysctl;
for (i = 0; i < NR_CPUS; i++)
INIT_LIST_HEAD(&done_q[i]);
@@ -1018,6 +1016,8 @@ static int __init init_scsi(void)
printk(KERN_NOTICE "SCSI subsystem initialized\n");
return 0;
+cleanup_sysctl:
+ scsi_exit_sysctl();
cleanup_hosts:
scsi_exit_hosts();
cleanup_devlist:
@@ -1034,6 +1034,7 @@ cleanup_queue:
static void __exit exit_scsi(void)
{
scsi_sysfs_unregister();
+ scsi_exit_sysctl();
scsi_exit_hosts();
scsi_exit_devinfo();
devfs_remove("scsi");
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 8424c445c6b7..4b5a903704b4 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -381,6 +381,7 @@ int scsi_get_device_flags(unsigned char *vendor, unsigned char *model)
return scsi_default_dev_flags;
}
+#ifdef CONFIG_SCSI_PROC_FS
/*
* proc_scsi_dev_info_read: dump the scsi_dev_info_list via
* /proc/scsi/device_info
@@ -451,6 +452,7 @@ out:
free_page((unsigned long)buffer);
return err;
}
+#endif /* CONFIG_SCSI_PROC_FS */
module_param_string(dev_flags, scsi_dev_flags, sizeof(scsi_dev_flags), 0);
MODULE_PARM_DESC(dev_flags,
@@ -471,7 +473,9 @@ void scsi_exit_devinfo(void)
struct list_head *lh, *lh_next;
struct scsi_dev_info_list *devinfo;
+#ifdef CONFIG_SCSI_PROC_FS
remove_proc_entry("scsi/device_info", 0);
+#endif
list_for_each_safe(lh, lh_next, &scsi_dev_info_list) {
devinfo = list_entry(lh, struct scsi_dev_info_list,
@@ -490,7 +494,9 @@ void scsi_exit_devinfo(void)
**/
int scsi_init_devinfo(void)
{
+#ifdef CONFIG_SCSI_PROC_FS
struct proc_dir_entry *p;
+#endif
int error, i;
error = scsi_dev_info_list_add_str(scsi_dev_flags);
@@ -507,6 +513,7 @@ int scsi_init_devinfo(void)
goto out;
}
+#ifdef CONFIG_SCSI_PROC_FS
p = create_proc_entry("scsi/device_info", 0, NULL);
if (!p) {
error = -ENOMEM;
@@ -516,6 +523,7 @@ int scsi_init_devinfo(void)
p->owner = THIS_MODULE;
p->get_info = proc_scsi_devinfo_read;
p->write_proc = proc_scsi_devinfo_write;
+#endif /* CONFIG_SCSI_PROC_FS */
out:
if (error)
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 6e4906ab2241..fce6a580363c 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1339,7 +1339,7 @@ static void scsi_eh_lock_done(struct scsi_cmnd *scmd)
**/
static void scsi_eh_lock_door(struct scsi_device *sdev)
{
- struct scsi_request *sreq = scsi_allocate_request(sdev);
+ struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
if (unlikely(!sreq)) {
printk(KERN_ERR "%s: request allocate failed,"
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 3dfdcf1f5bc8..53d4b5dd5344 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -98,7 +98,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd));
- sreq = scsi_allocate_request(sdev);
+ sreq = scsi_allocate_request(sdev, GFP_KERNEL);
if (!sreq) {
printk("SCSI internal ioctl failed, no memory\n");
return -ENOMEM;
@@ -321,7 +321,7 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
break;
}
- sreq = scsi_allocate_request(sdev);
+ sreq = scsi_allocate_request(sdev, GFP_KERNEL);
if (!sreq) {
result = -EINTR;
goto error;
@@ -408,30 +408,6 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void *arg)
return 0;
case SCSI_IOCTL_GET_BUS_NUMBER:
return put_user(sdev->host->host_no, (int *)arg);
- /*
- * The next two ioctls either need to go or need to be changed to
- * pass tagged queueing changes through the low level drivers.
- * Simply enabling or disabling tagged queueing without the knowledge
- * of the low level driver is a *BAD* thing.
- *
- * Oct. 10, 2002 - Doug Ledford <dledford@redhat.com>
- */
- case SCSI_IOCTL_TAGGED_ENABLE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (!sdev->tagged_supported)
- return -EINVAL;
- sdev->tagged_queue = 1;
- sdev->current_tag = 1;
- return 0;
- case SCSI_IOCTL_TAGGED_DISABLE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (!sdev->tagged_supported)
- return -EINVAL;
- sdev->tagged_queue = 0;
- sdev->current_tag = 0;
- return 0;
case SCSI_IOCTL_PROBE_HOST:
return ioctl_probe(sdev->host, arg);
case SCSI_IOCTL_SEND_COMMAND:
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 415be0cf47b0..e9e374cbdb4f 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1454,7 +1454,7 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
unsigned char *buffer, int len, int timeout, int retries,
struct scsi_mode_data *data)
{
- struct scsi_request *sreq = scsi_allocate_request(sdev);
+ struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
int ret;
if (!sreq)
diff --git a/drivers/scsi/scsi_logging.h b/drivers/scsi/scsi_logging.h
index a282c84c8ef5..b0a31a11ffcf 100644
--- a/drivers/scsi/scsi_logging.h
+++ b/drivers/scsi/scsi_logging.h
@@ -37,39 +37,23 @@
#define SCSI_LOG_HLCOMPLETE_BITS 3
#define SCSI_LOG_IOCTL_BITS 3
+extern unsigned int scsi_logging_level;
#ifdef CONFIG_SCSI_LOGGING
-extern unsigned int scsi_logging_level;
#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \
{ \
unsigned int mask = (1 << (BITS)) - 1; \
if (((scsi_logging_level >> (SHIFT)) & mask) > (LEVEL)) \
(CMD); \
}
-
-#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) \
-{ \
- unsigned int mask = ((1 << (BITS)) - 1) << SHIFT; \
- scsi_logging_level = ((scsi_logging_level & ~mask) \
- | ((LEVEL << SHIFT) & mask)); \
-}
#else
-/*
- * With no logging enabled, stub these out so they don't do anything.
- */
#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD)
-#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL)
#endif /* CONFIG_SCSI_LOGGING */
/*
* These are the macros that are actually used throughout the code to
* log events. If logging isn't enabled, they are no-ops and will be
* completely absent from the user's code.
- *
- * The 'set' versions of the macros are really intended to only be called
- * from the /proc filesystem, and in production kernels this will be about
- * all that is ever used. It could be useful in a debugging environment to
- * bump the logging level when certain strange events are detected, however.
*/
#define SCSI_LOG_ERROR_RECOVERY(LEVEL,CMD) \
SCSI_CHECK_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL,CMD);
@@ -92,26 +76,4 @@ extern unsigned int scsi_logging_level;
#define SCSI_LOG_IOCTL(LEVEL,CMD) \
SCSI_CHECK_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL,CMD);
-
-#define SCSI_SET_ERROR_RECOVERY_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL);
-#define SCSI_SET_TIMEOUT_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL);
-#define SCSI_SET_SCAN_BUS_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL);
-#define SCSI_SET_MLQUEUE_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL);
-#define SCSI_SET_MLCOMPLETE_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL);
-#define SCSI_SET_LLQUEUE_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL);
-#define SCSI_SET_LLCOMPLETE_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL);
-#define SCSI_SET_HLQUEUE_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL);
-#define SCSI_SET_HLCOMPLETE_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL);
-#define SCSI_SET_IOCTL_LOGGING(LEVEL) \
- SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL);
-
#endif /* _SCSI_LOGGING_H */
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 8608752c0fa4..62123cefb4c3 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -1,6 +1,17 @@
#ifndef _SCSI_PRIV_H
#define _SCSI_PRIV_H
+#include <linux/config.h>
+#include <linux/device.h>
+
+struct request_queue;
+struct scsi_cmnd;
+struct scsi_device;
+struct scsi_host_template;
+struct scsi_request;
+struct Scsi_Host;
+
+
/*
* These are the values that the owner field can take.
* They are used as an indication of who the command belongs to.
@@ -98,7 +109,7 @@ extern int scsi_init_queue(void);
extern void scsi_exit_queue(void);
/* scsi_proc.c */
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SCSI_PROC_FS
extern void scsi_proc_hostdir_add(struct scsi_host_template *);
extern void scsi_proc_hostdir_rm(struct scsi_host_template *);
extern void scsi_proc_host_add(struct Scsi_Host *);
@@ -115,12 +126,21 @@ extern void scsi_exit_procfs(void);
#endif /* CONFIG_PROC_FS */
/* scsi_scan.c */
-int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, unsigned int,
- unsigned int, int);
+extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int,
+ unsigned int, unsigned int, int);
extern void scsi_forget_host(struct Scsi_Host *);
extern void scsi_free_sdev(struct scsi_device *);
extern void scsi_rescan_device(struct device *);
+/* scsi_sysctl.c */
+#ifdef CONFIG_SYSCTL
+extern int scsi_init_sysctl(void);
+extern void scsi_exit_sysctl(void);
+#else
+# define scsi_init_sysctl() (0)
+# define scsi_exit_sysctl() do { } while (0)
+#endif /* CONFIG_SYSCTL */
+
/* scsi_sysfs.c */
extern int scsi_device_register(struct scsi_device *);
extern int scsi_sysfs_add_host(struct Scsi_Host *);
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index dd8bfd4b36c6..f72dd45bb651 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -37,9 +37,7 @@
/* 4K page size, but our output routines, use some slack for overruns */
#define PROC_BLOCK_SIZE (3*1024)
-/* XXX: this shouldn't really be exposed to drivers. */
-struct proc_dir_entry *proc_scsi;
-EXPORT_SYMBOL(proc_scsi);
+static struct proc_dir_entry *proc_scsi;
/* Protect sht->present and sht->proc_dir */
static DECLARE_MUTEX(global_host_template_sem);
@@ -235,106 +233,28 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
char *buffer, *p;
int err;
- if (!buf || length>PAGE_SIZE)
+ if (!buf || length > PAGE_SIZE)
return -EINVAL;
buffer = (char *)__get_free_page(GFP_KERNEL);
if (!buffer)
return -ENOMEM;
- if (copy_from_user(buffer, buf, length)) {
- err =-EFAULT;
+
+ err = -EFAULT;
+ if (copy_from_user(buffer, buf, length))
goto out;
- }
err = -EINVAL;
-
if (length < PAGE_SIZE)
buffer[length] = '\0';
else if (buffer[PAGE_SIZE-1])
goto out;
- if (length < 11 || strncmp("scsi", buffer, 4))
- goto out;
-
-#ifdef CONFIG_SCSI_LOGGING
- /*
- * Usage: echo "scsi log token #N" > /proc/scsi/scsi
- * where token is one of [error,scan,mlqueue,mlcomplete,llqueue,
- * llcomplete,hlqueue,hlcomplete]
- */
- if (!strncmp("log", buffer + 5, 3)) {
- char *token;
- unsigned int level;
-
- p = buffer + 9;
- token = p;
- while (*p != ' ' && *p != '\t' && *p != '\0') {
- p++;
- }
-
- if (*p == '\0') {
- if (strncmp(token, "all", 3) == 0) {
- /*
- * Turn on absolutely everything.
- */
- scsi_logging_level = ~0;
- } else if (strncmp(token, "none", 4) == 0) {
- /*
- * Turn off absolutely everything.
- */
- scsi_logging_level = 0;
- } else {
- goto out;
- }
- } else {
- *p++ = '\0';
-
- level = simple_strtoul(p, NULL, 0);
-
- /*
- * Now figure out what to do with it.
- */
- if (strcmp(token, "error") == 0) {
- SCSI_SET_ERROR_RECOVERY_LOGGING(level);
- } else if (strcmp(token, "timeout") == 0) {
- SCSI_SET_TIMEOUT_LOGGING(level);
- } else if (strcmp(token, "scan") == 0) {
- SCSI_SET_SCAN_BUS_LOGGING(level);
- } else if (strcmp(token, "mlqueue") == 0) {
- SCSI_SET_MLQUEUE_LOGGING(level);
- } else if (strcmp(token, "mlcomplete") == 0) {
- SCSI_SET_MLCOMPLETE_LOGGING(level);
- } else if (strcmp(token, "llqueue") == 0) {
- SCSI_SET_LLQUEUE_LOGGING(level);
- } else if (strcmp(token, "llcomplete") == 0) {
- SCSI_SET_LLCOMPLETE_LOGGING(level);
- } else if (strcmp(token, "hlqueue") == 0) {
- SCSI_SET_HLQUEUE_LOGGING(level);
- } else if (strcmp(token, "hlcomplete") == 0) {
- SCSI_SET_HLCOMPLETE_LOGGING(level);
- } else if (strcmp(token, "ioctl") == 0) {
- SCSI_SET_IOCTL_LOGGING(level);
- } else {
- goto out;
- }
- }
-
- printk(KERN_INFO "scsi logging level set to 0x%8.8x\n", scsi_logging_level);
- }
-#endif /* CONFIG_SCSI_LOGGING */
-
/*
* Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi
* with "0 1 2 3" replaced by your "Host Channel Id Lun".
- * Consider this feature BETA.
- * CAUTION: This is not for hotplugging your peripherals. As
- * SCSI was not designed for this you could damage your
- * hardware !
- * However perhaps it is legal to switch on an
- * already connected device. It is perhaps not
- * guaranteed this device doesn't corrupt an ongoing data transfer.
*/
- if (!strncmp("add-single-device", buffer + 5, 17)) {
+ if (!strncmp("scsi add-single-device", buffer, 22)) {
p = buffer + 23;
host = simple_strtoul(p, &p, 0);
@@ -345,18 +265,12 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
err = scsi_add_single_device(host, channel, id, lun);
if (err >= 0)
err = length;
+
/*
* Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi
* with "0 1 2 3" replaced by your "Host Channel Id Lun".
- *
- * Consider this feature pre-BETA.
- *
- * CAUTION: This is not for hotplugging your peripherals. As
- * SCSI was not designed for this you could damage your
- * hardware and thoroughly confuse the SCSI subsystem.
- *
*/
- } else if (!strncmp("remove-single-device", buffer + 5, 20)) {
+ } else if (!strncmp("scsi remove-single-device", buffer, 25)) {
p = buffer + 26;
host = simple_strtoul(p, &p, 0);
@@ -366,8 +280,8 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf,
err = scsi_remove_single_device(host, channel, id, lun);
}
-out:
-
+
+ out:
free_page((unsigned long)buffer);
return err;
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index cef0c4467a92..65807367d046 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -30,6 +30,7 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/blkdev.h>
+#include <asm/semaphore.h>
#include "scsi.h"
#include "hosts.h"
@@ -94,6 +95,13 @@ MODULE_PARM_DESC(max_report_luns,
" between 1 and 16384)");
#endif
+/*
+ * This mutex serializes all scsi scanning activity from kernel- and
+ * userspace. It could easily be made per-host but I'd like to avoid
+ * the overhead for now.
+ */
+static DECLARE_MUTEX(scsi_scan_mutex);
+
/**
* scsi_unlock_floptical - unlock device via a special MODE SENSE command
* @sreq: used to send the command
@@ -685,7 +693,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
sdev = scsi_alloc_sdev(host, channel, id, lun);
if (!sdev)
goto out;
- sreq = scsi_allocate_request(sdev);
+ sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
if (!sreq)
goto out_free_sdev;
result = kmalloc(256, GFP_ATOMIC |
@@ -898,7 +906,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
if (bflags & BLIST_NOLUN)
return 0;
- sreq = scsi_allocate_request(sdev);
+ sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
if (!sreq)
goto out;
@@ -1067,9 +1075,12 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost,
struct scsi_device *sdev;
int res;
+ down(&scsi_scan_mutex);
res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1);
if (res != SCSI_SCAN_LUN_PRESENT)
sdev = ERR_PTR(-ENODEV);
+ up(&scsi_scan_mutex);
+
return sdev;
}
@@ -1191,11 +1202,14 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
return -EINVAL;
+ down(&scsi_scan_mutex);
if (channel == SCAN_WILD_CARD)
for (channel = 0; channel <= shost->max_channel; channel++)
scsi_scan_channel(shost, channel, id, lun, rescan);
else
scsi_scan_channel(shost, channel, id, lun, rescan);
+ up(&scsi_scan_mutex);
+
return 0;
}
diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c
new file mode 100644
index 000000000000..04d06c25132b
--- /dev/null
+++ b/drivers/scsi/scsi_sysctl.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2003 Christoph Hellwig.
+ * Released under GPL v2.
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sysctl.h>
+
+#include "scsi_logging.h"
+
+
+static ctl_table scsi_table[] = {
+ { .ctl_name = DEV_SCSI_LOGGING_LEVEL,
+ .procname = "logging_level",
+ .data = &scsi_logging_level,
+ .maxlen = sizeof(scsi_logging_level),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec },
+ { }
+};
+
+static ctl_table scsi_dir_table[] = {
+ { .ctl_name = DEV_SCSI,
+ .procname = "scsi",
+ .mode = 0555,
+ .child = scsi_table },
+ { }
+};
+
+static ctl_table scsi_root_table[] = {
+ { .ctl_name = CTL_DEV,
+ .procname = "dev",
+ .mode = 0555,
+ .child = scsi_dir_table },
+ { }
+};
+
+static struct ctl_table_header *scsi_table_header;
+
+int __init scsi_init_sysctl(void)
+{
+ scsi_table_header = register_sysctl_table(scsi_root_table, 1);
+ if (!scsi_table_header)
+ return -ENOMEM;
+ return 0;
+}
+
+void scsi_exit_sysctl(void)
+{
+ unregister_sysctl_table(scsi_table_header);
+}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 2d9c592537b7..2bd0ee80e138 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -370,25 +370,24 @@ static int sd_open(struct inode *inode, struct file *filp)
if (!scsi_block_when_processing_errors(sdev))
goto error_out;
- if (sdev->removable) {
+ if (sdev->removable || sdkp->write_prot)
check_disk_change(inode->i_bdev);
- /*
- * If the drive is empty, just let the open fail.
- */
- retval = -ENOMEDIUM;
- if ((!sdkp->media_present) && !(filp->f_flags & O_NDELAY))
- goto error_out;
+ /*
+ * If the drive is empty, just let the open fail.
+ */
+ retval = -ENOMEDIUM;
+ if (sdev->removable && !sdkp->media_present &&
+ !(filp->f_flags & O_NDELAY))
+ goto error_out;
- /*
- * Similarly, if the device has the write protect tab set,
- * have the open fail if the user expects to be able to write
- * to the thing.
- */
- retval = -EROFS;
- if ((sdkp->write_prot) && (filp->f_mode & FMODE_WRITE))
- goto error_out;
- }
+ /*
+ * If the device has the write protect tab set, have the open fail
+ * if the user expects to be able to write to the thing.
+ */
+ retval = -EROFS;
+ if (sdkp->write_prot && (filp->f_mode & FMODE_WRITE))
+ goto error_out;
/*
* It is possible that the disk changing stuff resulted in
@@ -1174,7 +1173,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
if (!sdp->online)
goto out;
- sreq = scsi_allocate_request(sdp);
+ sreq = scsi_allocate_request(sdp, GFP_KERNEL);
if (!sreq) {
printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation "
"failure.\n");
@@ -1355,12 +1354,12 @@ static int sd_remove(struct device *dev)
static void sd_shutdown(struct device *dev)
{
struct scsi_device *sdp = to_scsi_device(dev);
- struct scsi_disk *sdkp;
+ struct scsi_disk *sdkp;
struct scsi_request *sreq;
int retries, res;
- sdkp = dev_get_drvdata(dev);
- if (!sdkp)
+ sdkp = dev_get_drvdata(dev);
+ if (!sdkp)
return; /* this can happen */
if (!sdp->online || !sdkp->WCE)
@@ -1369,7 +1368,7 @@ static void sd_shutdown(struct device *dev)
printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ",
sdkp->disk->disk_name);
- sreq = scsi_allocate_request(sdp);
+ sreq = scsi_allocate_request(sdp, GFP_KERNEL);
if (!sreq) {
printk("FAILED\n No memory for request\n");
return;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 813364338aea..0a5497ea2389 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -70,7 +70,7 @@ static int sg_version_num = 30529; /* 2 digits for each component */
#include "scsi_logging.h"
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SCSI_PROC_FS
#include <linux/proc_fs.h>
static int sg_proc_init(void);
static void sg_proc_cleanup(void);
@@ -222,7 +222,7 @@ static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
// static void sg_unmap_and(Sg_scatter_hold * schp, int free_also);
static Sg_device *sg_get_dev(int dev);
static inline unsigned char *sg_scatg2virt(const struct scatterlist *sclp);
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SCSI_PROC_FS
static int sg_last_dev(void);
#endif
@@ -680,7 +680,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
sg_finish_rem_req(srp);
return -ENODEV;
}
- SRpnt = scsi_allocate_request(sdp->device);
+ SRpnt = scsi_allocate_request(sdp->device, GFP_ATOMIC);
if (SRpnt == NULL) {
SCSI_LOG_TIMEOUT(1, printk("sg_write: no mem\n"));
sg_finish_rem_req(srp);
@@ -1516,18 +1516,18 @@ init_sg(void)
rc = scsi_register_interface(&sg_interface);
if (rc)
return rc;
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SCSI_PROC_FS
sg_proc_init();
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_SCSI_PROC_FS */
return 0;
}
static void __exit
exit_sg(void)
{
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SCSI_PROC_FS
sg_proc_cleanup();
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_SCSI_PROC_FS */
scsi_unregister_interface(&sg_interface);
unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
if (sg_dev_arr != NULL) {
@@ -2225,7 +2225,7 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
return resp;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SCSI_PROC_FS
static Sg_request *
sg_get_nth_request(Sg_fd * sfp, int nth)
{
@@ -2317,7 +2317,7 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp)
return res;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SCSI_PROC_FS
static Sg_fd *
sg_get_nth_sfp(Sg_device * sdp, int nth)
{
@@ -2548,7 +2548,7 @@ sg_allow_access(unsigned char opcode, char dev_type)
return 0;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SCSI_PROC_FS
static int
sg_last_dev(void)
{
@@ -2579,11 +2579,11 @@ sg_get_dev(int dev)
return sdp;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SCSI_PROC_FS
static struct proc_dir_entry *sg_proc_sgp = NULL;
-static char sg_proc_sg_dirname[] = "sg";
+static char sg_proc_sg_dirname[] = "scsi/sg";
static int sg_proc_adio_read(char *buffer, char **start, off_t offset,
int size, int *eof, void *data);
@@ -2657,10 +2657,6 @@ static struct sg_proc_leaf sg_proc_leaf_arr[] = {
size : begin + len - offset; \
} while(0)
-/* this should _really_ be private to the scsi midlayer. But
- /proc/scsi/sg is an established name, so.. */
-extern struct proc_dir_entry *proc_scsi;
-
static int
sg_proc_init(void)
{
@@ -2670,10 +2666,8 @@ sg_proc_init(void)
struct proc_dir_entry *pdep;
struct sg_proc_leaf * leaf;
- if (!proc_scsi)
- return 1;
sg_proc_sgp = create_proc_entry(sg_proc_sg_dirname,
- S_IFDIR | S_IRUGO | S_IXUGO, proc_scsi);
+ S_IFDIR | S_IRUGO | S_IXUGO, NULL);
if (!sg_proc_sgp)
return 1;
for (k = 0; k < num_leaves; ++k) {
@@ -2696,11 +2690,11 @@ sg_proc_cleanup(void)
int num_leaves =
sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]);
- if ((!proc_scsi) || (!sg_proc_sgp))
+ if (!sg_proc_sgp)
return;
for (k = 0; k < num_leaves; ++k)
remove_proc_entry(sg_proc_leaf_arr[k].name, sg_proc_sgp);
- remove_proc_entry(sg_proc_sg_dirname, proc_scsi);
+ remove_proc_entry(sg_proc_sg_dirname, NULL);
}
static int
@@ -2971,7 +2965,7 @@ sg_proc_version_info(char *buffer, int *len, off_t * begin,
PRINT_PROC("%d\t%s\n", sg_version_num, sg_version_str);
return 1;
}
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_SCSI_PROC_FS */
module_init(init_sg);
module_exit(exit_sg);
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index bbef9a48030f..089510b7a819 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -599,7 +599,7 @@ static void get_sectorsize(struct scsi_cd *cd)
buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer)
goto Enomem;
- SRpnt = scsi_allocate_request(cd->device);
+ SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
if (!SRpnt)
goto Enomem;
@@ -713,7 +713,7 @@ static void get_capabilities(struct scsi_cd *cd)
};
/* allocate a request for the TEST_UNIT_READY */
- SRpnt = scsi_allocate_request(cd->device);
+ SRpnt = scsi_allocate_request(cd->device, GFP_KERNEL);
if (!SRpnt) {
printk(KERN_WARNING "(get_capabilities:) Request allocation "
"failure.\n");
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 7eb274c0a33d..0416030f717f 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -82,7 +82,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct cdrom_generic_command *cgc)
int result, err = 0, retries = 0;
SDev = cd->device;
- SRpnt = scsi_allocate_request(SDev);
+ SRpnt = scsi_allocate_request(SDev, GFP_KERNEL);
if (!SRpnt) {
printk(KERN_ERR "Unable to allocate SCSI request in sr_do_ioctl");
err = -ENOMEM;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 85969cd26c84..ed0a5ab2667b 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -374,7 +374,7 @@ static Scsi_Request *
unsigned char *bp;
if (SRpnt == NULL) {
- SRpnt = scsi_allocate_request(STp->device);
+ SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC);
if (SRpnt == NULL) {
DEBC( printk(KERN_ERR "%s: Can't get SCSI request.\n",
tape_name(STp)); );
diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
index c549d49e3c30..a31642785f19 100644
--- a/drivers/scsi/sym53c8xx.c
+++ b/drivers/scsi/sym53c8xx.c
@@ -6594,19 +6594,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
}
cp->cmd = cmd;
- /*---------------------------------------------------
- **
- ** Enable tagged queue if asked by scsi ioctl
- **
- **----------------------------------------------------
- */
-#if 0 /* This stuff was only useful for linux-1.2.13 */
- if (lp && !lp->numtags && cmd->device && cmd->device->tagged_queue) {
- lp->numtags = tp->usrtags;
- ncr_setup_tags (np, cp->target, cp->lun);
- }
-#endif
-
/*----------------------------------------------------
**
** Build the identify / tag / sdtr message
diff --git a/drivers/scsi/sym53c8xx_2/sym_conf.h b/drivers/scsi/sym53c8xx_2/sym_conf.h
index 8bc52f731a5a..705ffaadb31f 100644
--- a/drivers/scsi/sym53c8xx_2/sym_conf.h
+++ b/drivers/scsi/sym53c8xx_2/sym_conf.h
@@ -131,11 +131,6 @@
/* #define SYM_CONF_IARB_SUPPORT */
/*
- * Support for some PCI fix-ups (or assumed so).
- */
-#define SYM_CONF_PCI_FIX_UP
-
-/*
* Number of lists for the optimization of the IO timeout handling.
* Not used under FreeBSD and Linux.
*/
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 70649d107d6a..f8344b42dfd1 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -74,8 +74,8 @@
#define PCI_ID_SYM53C896 0xb
#define PCI_ID_SYM53C895A 0x12
#define PCI_ID_SYM53C875A 0x13
-#define PCI_ID_LSI53C1010 0x20
-#define PCI_ID_LSI53C1010_2 0x21
+#define PCI_ID_LSI53C1010_33 0x20
+#define PCI_ID_LSI53C1010_66 0x21
#define PCI_ID_LSI53C1510D 0xa
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
index bcdd7c5297e0..5b24d1fe9652 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c
@@ -270,13 +270,13 @@ sym_fw2_patch(hcb_p np)
* Remove a couple of work-arounds specific to C1010 if
* they are not desirable. See `sym_fw2.h' for more details.
*/
- if (!(np->device_id == PCI_ID_LSI53C1010_2 &&
+ if (!(np->device_id == PCI_ID_LSI53C1010_66 &&
np->revision_id < 0x1 &&
np->pciclk_khz < 60000)) {
scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
scripta0->datao_phase[1] = cpu_to_scr(0);
}
- if (!(np->device_id == PCI_ID_LSI53C1010 &&
+ if (!(np->device_id == PCI_ID_LSI53C1010_33 &&
/* np->revision_id < 0xff */ 1)) {
scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
scripta0->sel_done[1] = cpu_to_scr(0);
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index a8cb6c5ad4fe..26dcbea2b562 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -57,7 +57,7 @@
#define NAME53C "sym53c"
#define NAME53C8XX "sym53c8xx"
-static int __init
+static int __devinit
pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
{
u32 tmp;
@@ -77,30 +77,6 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
#undef PCI_BAR_OFFSET
}
-/*
- * Insert a delay in micro-seconds and milli-seconds.
- */
-void sym_udelay(int us) { udelay(us); }
-void sym_mdelay(int ms) { mdelay(ms); }
-
-/*
- * SMP threading.
- *
- * The whole SCSI sub-system under Linux is basically single-threaded.
- * Everything, including low-level driver interrupt routine, happens
- * with the `io_request_lock' held.
- * The sym53c8xx-1.x drivers series ran their interrupt code using a
- * spin mutex per controller. This added complexity without improving
- * scalability significantly. the sym-2 driver still use a spinlock
- * per controller for safety, but basically runs with the damned
- * io_request_lock held.
- */
-
-spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
-
-#define SYM_LOCK_DRIVER(flags) spin_lock_irqsave(&sym53c8xx_lock, flags)
-#define SYM_UNLOCK_DRIVER(flags) spin_unlock_irqrestore(&sym53c8xx_lock,flags)
-
#define SYM_INIT_LOCK_HCB(np) spin_lock_init((np)->s.host->host_lock);
#define SYM_LOCK_HCB(np, flags) \
spin_lock_irqsave((np)->s.host->host_lock, flags)
@@ -118,6 +94,9 @@ spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
#define ktime_add(a, o) ((a) + (u_long)(o))
#define ktime_sub(a, o) ((a) - (u_long)(o))
+/* This lock protects only the memory allocation/free. */
+spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
+
/*
* Wrappers to the generic memory allocator.
*/
@@ -125,58 +104,53 @@ void *sym_calloc(int size, char *name)
{
u_long flags;
void *m;
- SYM_LOCK_DRIVER(flags);
+ spin_lock_irqsave(&sym53c8xx_lock, flags);
m = sym_calloc_unlocked(size, name);
- SYM_UNLOCK_DRIVER(flags);
+ spin_unlock_irqrestore(&sym53c8xx_lock, flags);
return m;
}
void sym_mfree(void *m, int size, char *name)
{
u_long flags;
- SYM_LOCK_DRIVER(flags);
+ spin_lock_irqsave(&sym53c8xx_lock, flags);
sym_mfree_unlocked(m, size, name);
- SYM_UNLOCK_DRIVER(flags);
+ spin_unlock_irqrestore(&sym53c8xx_lock, flags);
}
-#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
-
void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name)
{
u_long flags;
void *m;
- SYM_LOCK_DRIVER(flags);
+ spin_lock_irqsave(&sym53c8xx_lock, flags);
m = __sym_calloc_dma_unlocked(dev_dmat, size, name);
- SYM_UNLOCK_DRIVER(flags);
+ spin_unlock_irqrestore(&sym53c8xx_lock, flags);
return m;
}
void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name)
{
u_long flags;
- SYM_LOCK_DRIVER(flags);
+ spin_lock_irqsave(&sym53c8xx_lock, flags);
__sym_mfree_dma_unlocked(dev_dmat, m, size, name);
- SYM_UNLOCK_DRIVER(flags);
+ spin_unlock_irqrestore(&sym53c8xx_lock, flags);
}
m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m)
{
u_long flags;
m_addr_t b;
- SYM_LOCK_DRIVER(flags);
+ spin_lock_irqsave(&sym53c8xx_lock, flags);
b = __vtobus_unlocked(dev_dmat, m);
- SYM_UNLOCK_DRIVER(flags);
+ spin_unlock_irqrestore(&sym53c8xx_lock, flags);
return b;
}
-#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
-
-
/*
* Map/unmap a PCI memory window.
*/
#ifndef SYM_OPT_NO_BUS_MEMORY_MAPPING
-static u_long __init pci_map_mem(u_long base, u_long size)
+static u_long __devinit pci_map_mem(u_long base, u_long size)
{
u_long page_base = ((u_long) base) & PAGE_MASK;
u_long page_offs = ((u_long) base) - page_base;
@@ -185,19 +159,13 @@ static u_long __init pci_map_mem(u_long base, u_long size)
return page_remapped? (page_remapped + page_offs) : 0UL;
}
-static void __init pci_unmap_mem(u_long vaddr, u_long size)
+static void __devinit pci_unmap_mem(u_long vaddr, u_long size)
{
if (vaddr)
iounmap((void *) (vaddr & PAGE_MASK));
}
#endif
-/*
- * Used to retrieve the host structure when the
- * driver is called from the proc FS.
- */
-static struct Scsi_Host *first_host = NULL;
-
#define scsi_data_direction(cmd) (cmd->sc_data_direction)
/*
@@ -210,11 +178,7 @@ struct host_data {
/*
* Some type that fit DMA addresses as seen from BUS.
*/
-#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING
-typedef u_long bus_addr_t;
-#else
typedef dma_addr_t bus_addr_t;
-#endif
/*
* Used by the eh thread to wait for command completion.
@@ -233,10 +197,8 @@ struct sym_eh_wait {
*/
struct sym_ucmd { /* Override the SCSI pointer structure */
SYM_QUEHEAD link_cmdq; /* Must stay at offset ZERO */
-#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
bus_addr_t data_mapping;
u_char data_mapped;
-#endif
struct sym_eh_wait *eh_wait;
};
@@ -249,39 +211,18 @@ typedef struct sym_ucmd *ucmd_p;
/*
* Deal with DMA mapping/unmapping.
*/
-
-#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING
-
-/* Linux versions prior to pci bus iommu kernel interface */
-
-#define __unmap_scsi_data(pdev, cmd) do {; } while (0)
-#define __map_scsi_single_data(pdev, cmd) (__vtobus(pdev,(cmd)->request_buffer))
-#define __map_scsi_sg_data(pdev, cmd) ((cmd)->use_sg)
-#define __sync_scsi_data(pdev, cmd) do {; } while (0)
-
-#define bus_sg_dma_address(sc) vtobus((sc)->address)
-#define bus_sg_dma_len(sc) ((sc)->length)
-
-#else /* Linux version with pci bus iommu kernel interface */
-
#define bus_unmap_sg(pdev, sgptr, sgcnt, dir) \
pci_unmap_sg(pdev, sgptr, sgcnt, dir)
-
#define bus_unmap_single(pdev, mapping, bufptr, dir) \
pci_unmap_single(pdev, mapping, bufptr, dir)
-
#define bus_map_single(pdev, bufptr, bufsiz, dir) \
pci_map_single(pdev, bufptr, bufsiz, dir)
-
#define bus_map_sg(pdev, sgptr, sgcnt, dir) \
pci_map_sg(pdev, sgptr, sgcnt, dir)
-
#define bus_dma_sync_sg(pdev, sgptr, sgcnt, dir) \
pci_dma_sync_sg(pdev, sgptr, sgcnt, dir)
-
#define bus_dma_sync_single(pdev, mapping, bufsiz, dir) \
pci_dma_sync_single(pdev, mapping, bufsiz, dir)
-
#define bus_sg_dma_address(sc) sg_dma_address(sc)
#define bus_sg_dma_len(sc) sg_dma_len(sc)
@@ -345,8 +286,6 @@ static void __sync_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
}
}
-#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
-
#define unmap_scsi_data(np, cmd) \
__unmap_scsi_data(np->s.device, cmd)
#define map_scsi_single_data(np, cmd) \
@@ -1656,13 +1595,13 @@ static int sym_host_info(hcb_p np, char *ptr, off_t offset, int len)
copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
"revision id 0x%x\n",
np->s.chip_name, np->device_id, np->revision_id);
- copy_info(&info, "On PCI bus %d, device %d, function %d, "
+ copy_info(&info, "At PCI address %s, "
#ifdef __sparc__
"IRQ %s\n",
#else
"IRQ %d\n",
#endif
- np->s.bus, (np->s.device_fn & 0xf8) >> 3, np->s.device_fn & 7,
+ pci_name(np->s.device),
#ifdef __sparc__
__irq_itoa(np->s.irq));
#else
@@ -1748,7 +1687,6 @@ static void sym_free_resources(hcb_p np)
/*
* Ask/tell the system about DMA addressing.
*/
-#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
static int sym_setup_bus_dma_mask(hcb_p np)
{
#if SYM_CONF_DMA_ADDRESSING_MODE == 0
@@ -1780,7 +1718,6 @@ out_err32:
sym_name(np));
return -1;
}
-#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
/*
* Host attach and initialisations.
@@ -1791,7 +1728,7 @@ out_err32:
* If all is OK, install interrupt handling and
* start the timer daemon.
*/
-static int __init
+static int __devinit
sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev)
{
struct host_data *host_data;
@@ -1802,15 +1739,14 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev)
struct sym_fw *fw;
printk(KERN_INFO
- "sym%d: <%s> rev 0x%x on pci bus %d device %d function %d "
+ "sym%d: <%s> rev 0x%x at pci %s "
#ifdef __sparc__
"irq %s\n",
#else
"irq %d\n",
#endif
unit, dev->chip.name, dev->chip.revision_id,
- dev->s.bus, (dev->s.device_fn & 0xf8) >> 3,
- dev->s.device_fn & 7,
+ pci_name(dev->pdev),
#ifdef __sparc__
__irq_itoa(dev->s.irq));
#else
@@ -1837,7 +1773,6 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev)
* We keep track in the HCB of all the resources that
* are to be released on error.
*/
-#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
np = __sym_calloc_dma(dev->pdev, sizeof(*np), "HCB");
if (np) {
np->s.device = dev->pdev;
@@ -1845,11 +1780,7 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev)
}
else
goto attach_failed;
-#else
- np = sym_calloc_dma(sizeof(*np), "HCB");
- if (!np)
- goto attach_failed;
-#endif
+
host_data->ncb = np;
np->s.host = instance;
@@ -1866,8 +1797,6 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev)
np->s.unit = unit;
np->device_id = dev->chip.device_id;
np->revision_id = dev->chip.revision_id;
- np->s.bus = dev->s.bus;
- np->s.device_fn = dev->s.device_fn;
np->features = dev->chip.features;
np->clock_divn = dev->chip.nr_divisor;
np->maxoffs = dev->chip.offset_max;
@@ -1883,10 +1812,8 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev)
/*
* Ask/tell the system about DMA addressing.
*/
-#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
if (sym_setup_bus_dma_mask(np))
goto attach_failed;
-#endif
/*
* Try to map the controller chip to
@@ -1987,12 +1914,6 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev)
sym_timer (np);
/*
- * Done.
- */
- if (!first_host)
- first_host = instance;
-
- /*
* Fill Linux host instance structure
* and return success.
*/
@@ -2039,7 +1960,7 @@ attach_failed:
* Detect and try to read SYMBIOS and TEKRAM NVRAM.
*/
#if SYM_CONF_NVRAM_SUPPORT
-static void __init sym_get_nvram(sym_device *devp, sym_nvram *nvp)
+static void __devinit sym_get_nvram(sym_device *devp, sym_nvram *nvp)
{
if (!nvp)
return;
@@ -2087,37 +2008,6 @@ char *sym53c8xx = 0; /* command line passed by insmod */
MODULE_PARM(sym53c8xx, "s");
#endif
-static void __init sym53c8xx_print_driver_setup(void)
-{
- printf_info (NAME53C8XX ": setup="
- "mpar:%d,spar:%d,tags:%d,sync:%d,burst:%d,"
- "led:%d,wide:%d,diff:%d,irqm:%d, buschk:%d\n",
- sym_driver_setup.pci_parity,
- sym_driver_setup.scsi_parity,
- sym_driver_setup.max_tag,
- sym_driver_setup.min_sync,
- sym_driver_setup.burst_order,
- sym_driver_setup.scsi_led,
- sym_driver_setup.max_wide,
- sym_driver_setup.scsi_diff,
- sym_driver_setup.irq_mode,
- sym_driver_setup.scsi_bus_check);
- printf_info (NAME53C8XX ": setup="
- "hostid:%d,offs:%d,luns:%d,pcifix:%d,revprob:%d,"
- "verb:%d,debug:0x%x,setlle_delay:%d\n",
- sym_driver_setup.host_id,
- sym_driver_setup.max_offs,
- sym_driver_setup.max_lun,
- sym_driver_setup.pci_fix_up,
- sym_driver_setup.reverse_probe,
- sym_driver_setup.verbose,
- sym_driver_setup.debug,
- sym_driver_setup.settle_delay);
-#ifdef DEBUG_2_0_X
-MDELAY(5000);
-#endif
-};
-
#define OPT_PCI_PARITY 1
#define OPT_SCSI_PARITY 2
#define OPT_MAX_TAG 3
@@ -2131,15 +2021,13 @@ MDELAY(5000);
#define OPT_HOST_ID 11
#define OPT_MAX_OFFS 12
#define OPT_MAX_LUN 13
-#define OPT_PCI_FIX_UP 14
-
-#define OPT_REVERSE_PROBE 15
-#define OPT_VERBOSE 16
-#define OPT_DEBUG 17
-#define OPT_SETTLE_DELAY 18
-#define OPT_USE_NVRAM 19
-#define OPT_EXCLUDE 20
-#define OPT_SAFE_SETUP 21
+#define OPT_REVERSE_PROBE 14
+#define OPT_VERBOSE 15
+#define OPT_DEBUG 16
+#define OPT_SETTLE_DELAY 17
+#define OPT_USE_NVRAM 18
+#define OPT_EXCLUDE 19
+#define OPT_SAFE_SETUP 20
static char setup_token[] __initdata =
"mpar:" "spar:"
@@ -2148,11 +2036,10 @@ static char setup_token[] __initdata =
"wide:" "diff:"
"irqm:" "buschk:"
"hostid:" "offset:"
- "luns:" "pcifix:"
- "revprob:" "verb:"
- "debug:" "settle:"
- "nvram:" "excl:"
- "safe:"
+ "luns:" "revprob:"
+ "verb:" "debug:"
+ "settle:" "nvram:"
+ "excl:" "safe:"
;
#ifdef MODULE
@@ -2239,7 +2126,6 @@ int __init sym53c8xx_setup(char *str)
__SIMPLE_OPTION(HOST_ID, host_id)
__SIMPLE_OPTION(MAX_OFFS, max_offs)
__SIMPLE_OPTION(MAX_LUN, max_lun)
- __SIMPLE_OPTION(PCI_FIX_UP, pci_fix_up)
__SIMPLE_OPTION(REVERSE_PROBE, reverse_probe)
__SIMPLE_OPTION(VERBOSE, verbose)
__SIMPLE_OPTION(DEBUG, debug)
@@ -2269,19 +2155,16 @@ __setup("sym53c8xx=", sym53c8xx_setup);
* boards and save data for attaching after all boards have
* been detected.
*/
-static int __init
+static int __devinit
sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device)
{
- u_short vendor_id, device_id, command, status_reg;
- u_char cache_line_size;
- u_char suggested_cache_line_size = 0;
- u_char pci_fix_up = SYM_SETUP_PCI_FIX_UP;
+ u_short vendor_id, device_id, status_reg;
u_char revision;
u_int irq;
u_long base, base_2;
u_long base_c, base_2_c, io_port;
int i;
- sym_chip *chip;
+ struct sym_pci_chip *chip;
/* Choose some short name for this device */
sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number,
@@ -2393,25 +2276,6 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device)
pci_set_master(pdev);
/*
- * Read additionnal info from the configuration space.
- */
- pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
-
- /*
- * If cache line size is not configured, suggest
- * a value for well known CPUs.
- */
-#if defined(__i386__) && !defined(MODULE)
- if (!cache_line_size && boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
- switch(boot_cpu_data.x86) {
- case 4: suggested_cache_line_size = 4; break;
- case 6: if (boot_cpu_data.x86_model > 8) break;
- case 5: suggested_cache_line_size = 8; break;
- }
- }
-#endif /* __i386__ */
-
- /*
* Some features are required to be enabled in order to
* work around some chip problems. :) ;)
* (ITEM 12 of a DEL about the 896 I haven't yet).
@@ -2420,31 +2284,12 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device)
*/
if (device_id == PCI_DEVICE_ID_NCR_53C896 && revision < 0x4) {
chip->features |= (FE_WRIE | FE_CLSE);
- pci_fix_up |= 3; /* Force appropriate PCI fix-up */
- }
-
-#ifdef SYM_CONF_PCI_FIX_UP
- /*
- * Try to fix up PCI config according to wished features.
- */
- if ((pci_fix_up & 1) && (chip->features & FE_CLSE) &&
- !cache_line_size && suggested_cache_line_size) {
- cache_line_size = suggested_cache_line_size;
- pci_write_config_byte(pdev,
- PCI_CACHE_LINE_SIZE, cache_line_size);
- printf_info("%s: PCI_CACHE_LINE_SIZE set to %d.\n",
- sym_name(device), cache_line_size);
}
- pci_read_config_word(pdev, PCI_COMMAND, &command);
- if ((pci_fix_up & 2) && cache_line_size &&
- (chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) {
- printf_info("%s: setting PCI_COMMAND_INVALIDATE.\n",
- sym_name(device));
- command |= PCI_COMMAND_INVALIDATE;
- pci_write_config_word(pdev, PCI_COMMAND, command);
+ if (chip->features & FE_WRIE) {
+ if (pci_set_mwi(pdev))
+ return -1;
}
-#endif /* SYM_CONF_PCI_FIX_UP */
/*
* Work around for errant bit in 895A. The 66Mhz
@@ -2461,8 +2306,7 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device)
if (chip->features & FE_66MHZ) {
if (!(status_reg & PCI_STATUS_66MHZ))
chip->features &= ~FE_66MHZ;
- }
- else {
+ } else {
if (status_reg & PCI_STATUS_66MHZ) {
status_reg = PCI_STATUS_66MHZ;
pci_write_config_word(pdev, PCI_STATUS, status_reg);
@@ -2474,8 +2318,6 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device)
* Initialise device structure with items required by sym_attach.
*/
device->pdev = pdev;
- device->s.bus = pdev->bus->number;
- device->s.device_fn = pdev->devfn;
device->s.base = base;
device->s.base_2 = base_2;
device->s.base_c = base_c;
@@ -2487,203 +2329,6 @@ sym53c8xx_pci_init(struct pci_dev *pdev, sym_device *device)
return 0;
}
-#if 0
-/*
- * Detect all 53c8xx hosts and then attach them.
- *
- * If we are using NVRAM, once all hosts are detected, we need to
- * check any NVRAM for boot order in case detect and boot order
- * differ and attach them using the order in the NVRAM.
- *
- * If no NVRAM is found or data appears invalid attach boards in
- * the order they are detected.
- */
-int __init sym53c8xx_detect(struct scsi_host_template *tpnt)
-{
- struct pci_dev *pcidev;
- int i, j, chips, hosts, count;
- int attach_count = 0;
- sym_device *devtbl, *devp;
- sym_nvram nvram;
-#if SYM_CONF_NVRAM_SUPPORT
- sym_nvram nvram0, *nvp;
-#endif
-
- /*
- * Initialize driver general stuff.
- */
-#ifdef SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
-#ifdef MODULE
-if (sym53c8xx)
- sym53c8xx_setup(sym53c8xx);
-#endif
-#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
- sym_debug_flags = sym_driver_setup.debug;
-#endif
- if (boot_verbose >= 2)
- sym53c8xx_print_driver_setup();
-#endif /* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
-
- /*
- * Allocate the device table since we donnot want to
- * overflow the kernel stack.
- * 1 x 4K PAGE is enough for more than 40 devices for i386.
- */
- devtbl = sym_calloc(PAGE_SIZE, "DEVTBL");
- if (!devtbl)
- return 0;
-
- /*
- * Detect all NCR PQS/PDS memory controllers.
- */
-#ifdef SYM_CONF_PQS_PDS_SUPPORT
- sym_detect_pqs_pds();
-#endif
-
- /*
- * Detect all 53c8xx hosts.
- * Save the first Symbios NVRAM content if any
- * for the boot order.
- */
- chips = sizeof(sym_chip_ids) / sizeof(sym_chip_ids[0]);
- hosts = PAGE_SIZE / sizeof(*devtbl);
-#if SYM_CONF_NVRAM_SUPPORT
- nvp = (sym_driver_setup.use_nvram & 0x1) ? &nvram0 : 0;
-#endif
- j = 0;
- count = 0;
- pcidev = NULL;
- while (1) {
- char *msg = "";
- if (count >= hosts)
- break;
- if (j >= chips)
- break;
- i = sym_driver_setup.reverse_probe ? chips - 1 - j : j;
- pcidev = pci_find_device(PCI_VENDOR_ID_NCR, sym_chip_ids[i],
- pcidev);
- if (pcidev == NULL) {
- ++j;
- continue;
- }
- /* This one is guaranteed by AC to do nothing :-) */
- if (pci_enable_device(pcidev))
- continue;
- devp = &devtbl[count];
- devp->host_id = SYM_SETUP_HOST_ID;
- if (sym53c8xx_pci_init(pcidev, devp)) {
- continue;
- }
- ++count;
-#if SYM_CONF_NVRAM_SUPPORT
- if (nvp) {
- sym_get_nvram(devp, nvp);
- switch(nvp->type) {
- case SYM_SYMBIOS_NVRAM:
- /*
- * Switch to the other nvram buffer, so that
- * nvram0 will contain the first Symbios
- * format NVRAM content with boot order.
- */
- nvp = &nvram;
- msg = "with Symbios NVRAM";
- break;
- case SYM_TEKRAM_NVRAM:
- msg = "with Tekram NVRAM";
- break;
- }
- }
-#endif
-#ifdef SYM_CONF_PQS_PDS_SUPPORT
- /*
- * Match the BUS number for PQS/PDS devices.
- * Read the SCSI ID from a special register mapped
- * into the configuration space of the individual
- * 875s. This register is set up by the PQS bios
- */
- for(i = 0; i < SYM_CONF_MAX_PQS_BUS && pqs_bus[i] != -1; i++) {
- u_char tmp;
- if (pqs_bus[i] == pcidev->bus->number) {
- pci_read_config_byte(pcidev, 0x84, &tmp);
- devp->pqs_pds = 1;
- devp->host_id = tmp;
- break;
- }
- }
- if (devp->pqs_pds)
- msg = "(NCR PQS/PDS)";
-#endif
- if (boot_verbose)
- printf_info("%s: 53c%s detected %s\n",
- sym_name(devp), devp->chip.name, msg);
- }
-
- /*
- * If we have found a SYMBIOS NVRAM, use first the NVRAM boot
- * sequence as device boot order.
- * check devices in the boot record against devices detected.
- * attach devices if we find a match. boot table records that
- * do not match any detected devices will be ignored.
- * devices that do not match any boot table will not be attached
- * here but will attempt to be attached during the device table
- * rescan.
- */
-#if SYM_CONF_NVRAM_SUPPORT
- if (!nvp || nvram0.type != SYM_SYMBIOS_NVRAM)
- goto next;
- for (i = 0; i < 4; i++) {
- Symbios_host *h = &nvram0.data.Symbios.host[i];
- for (j = 0 ; j < count ; j++) {
- devp = &devtbl[j];
- if (h->device_fn != devp->s.device_fn ||
- h->bus_nr != devp->s.bus ||
- h->device_id != devp->chip.device_id)
- continue;
- if (devp->attach_done)
- continue;
- if (h->flags & SYMBIOS_INIT_SCAN_AT_BOOT) {
- sym_get_nvram(devp, nvp);
- if (!sym_attach (tpnt, attach_count, devp))
- attach_count++;
- }
- else if (!(sym_driver_setup.use_nvram & 0x80))
- printf_info(
- "%s: 53c%s state OFF thus not attached\n",
- sym_name(devp), devp->chip.name);
- else
- continue;
-
- devp->attach_done = 1;
- break;
- }
- }
-next:
-#endif
-
- /*
- * Rescan device list to make sure all boards attached.
- * Devices without boot records will not be attached yet
- * so try to attach them here.
- */
- for (i= 0; i < count; i++) {
- devp = &devtbl[i];
- if (!devp->attach_done) {
- devp->nvram = &nvram;
- nvram.type = 0;
-#if SYM_CONF_NVRAM_SUPPORT
- sym_get_nvram(devp, nvp);
-#endif
- if (!sym_attach (tpnt, attach_count, devp))
- attach_count++;
- }
- }
-
- sym_mfree(devtbl, PAGE_SIZE, "DEVTBL");
-
- return attach_count;
-}
-#endif
-
/*
* Linux release module stuff.
@@ -2717,15 +2362,6 @@ static int sym_detach(hcb_p np)
return 1;
}
-#if 0
-int sym53c8xx_release(struct Scsi_Host *host)
-{
- sym_detach(((struct host_data *) host->hostdata)->ncb);
-
- return 0;
-}
-#endif
-
MODULE_LICENSE("Dual BSD/GPL");
/*
@@ -2734,10 +2370,6 @@ MODULE_LICENSE("Dual BSD/GPL");
static struct scsi_host_template sym2_template = {
.module = THIS_MODULE,
.name = "sym53c8xx",
-#if 0
- .detect = sym53c8xx_detect,
- .release = sym53c8xx_release,
-#endif
.info = sym53c8xx_info,
.queuecommand = sym53c8xx_queue_command,
.slave_configure = sym53c8xx_slave_configure,
@@ -2839,7 +2471,6 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
sym_dev.host_id = SYM_SETUP_HOST_ID;
if (sym53c8xx_pci_init(pdev, &sym_dev))
return -ENODEV;
- printk(KERN_INFO "%s: 53c%s detected\n", sym_name(&sym_dev), sym_dev.chip.name);
sym_dev.nvram = &nvram;
nvram.type = 0;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index 5ee8c1b63f0f..a8f5a81cad40 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -111,8 +111,6 @@ typedef u_long vm_offset_t;
/*
* Configuration addendum for Linux.
*/
-#define SYM_LINUX_DYNAMIC_DMA_MAPPING
-
#define SYM_CONF_TIMER_INTERVAL ((HZ+1)/2)
#define SYM_OPT_HANDLE_DIR_UNKNOWN
@@ -121,10 +119,7 @@ typedef u_long vm_offset_t;
#define SYM_OPT_SNIFF_INQUIRY
#define SYM_OPT_LIMIT_COMMAND_REORDERING
#define SYM_OPT_ANNOUNCE_TRANSFER_RATE
-
-#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
#define SYM_OPT_BUS_DMA_ABSTRACTION
-#endif
/*
* Print a message with severity.
@@ -142,8 +137,8 @@ typedef u_long vm_offset_t;
/*
* Insert a delay in micro-seconds and milli-seconds.
*/
-void sym_udelay(int us);
-void sym_mdelay(int ms);
+#define sym_udelay(us) udelay(us)
+#define sym_mdelay(ms) mdelay(ms)
/*
* Let the compiler know about driver data structure names.
@@ -426,9 +421,6 @@ struct sym_shcb {
struct Scsi_Host *host;
- u_char bus; /* PCI BUS number */
- u_char device_fn; /* PCI BUS device and function */
-
vm_offset_t mmio_va; /* MMIO kernel virtual address */
vm_offset_t ram_va; /* RAM kernel virtual address */
u_long io_port; /* IO port address cookie */
@@ -455,8 +447,6 @@ struct sym_shcb {
* used as sub-field 's' of another structure.
*/
typedef struct {
- int bus;
- u_char device_fn;
u_long base;
u_long base_2;
u_long base_c;
@@ -469,12 +459,11 @@ typedef struct {
} sym_slot;
typedef struct sym_nvram sym_nvram;
-typedef struct sym_pci_chip sym_chip;
typedef struct {
struct pci_dev *pdev;
sym_slot s;
- sym_chip chip;
+ struct sym_pci_chip chip;
sym_nvram *nvram;
u_short device_id;
u_char host_id;
@@ -496,9 +485,7 @@ typedef u_long m_addr_t; /* Enough bits to represent any address */
#ifdef MODULE
#define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */
#endif
-#ifdef SYM_LINUX_DYNAMIC_DMA_MAPPING
typedef struct pci_dev *m_pool_ident_t;
-#endif
/*
* Include driver soft definitions.
@@ -521,19 +508,7 @@ typedef struct pci_dev *m_pool_ident_t;
void *sym_calloc(int size, char *name);
void sym_mfree(void *m, int size, char *name);
-#ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING
/*
- * Simple case.
- * All the memory assummed DMAable and O/S providing virtual
- * to bus physical address translation.
- */
-#define __sym_calloc_dma(pool_id, size, name) sym_calloc(size, name)
-#define __sym_mfree_dma(pool_id, m, size, name) sym_mfree(m, size, name)
-#define __vtobus(b, p) virt_to_bus(p)
-
-#else /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
-/*
- * Complex case.
* We have to provide the driver memory allocator with methods for
* it to maintain virtual to bus physical address translations.
*/
@@ -560,15 +535,12 @@ static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
}
#define sym_m_create_dma_mem_tag(mp) (0)
-
#define sym_m_delete_dma_mem_tag(mp) do { ; } while (0)
void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name);
void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name);
m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);
-#endif /* SYM_LINUX_DYNAMIC_DMA_MAPPING */
-
/*
* Set the status field of a CAM CCB.
*/
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 7d83f2c28869..a8984f6ee40e 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -50,7 +50,7 @@
* SUCH DAMAGE.
*/
-#define SYM_DRIVER_NAME "sym-2.1.16a"
+#define SYM_DRIVER_NAME "sym-2.1.17a"
#ifdef __FreeBSD__
#include <dev/sym/sym_glue.h>
@@ -289,7 +289,7 @@ int sym_reset_scsi_bus(hcb_p np, int enab_int)
((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */
INB(nc_sbcl); /* req ack bsy sel atn msg cd io */
- if (!(np->features & FE_WIDE))
+ if (!np->maxwide)
term &= 0x3ffff;
if (term != (2<<7)) {
@@ -744,6 +744,12 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
u32 period;
int i;
+#ifdef CONFIG_PARISC
+ unsigned long pdc_period;
+ char scsi_mode = -1;
+ struct hardware_path hwpath;
+#endif
+
/*
* Wide ?
*/
@@ -800,6 +806,31 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
* Btw, 'period' is in tenths of nanoseconds.
*/
period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
+
+#if defined(CONFIG_PARISC)
+ /* Host firmware (PDC) keeps a table for crippling SCSI capabilities.
+ * Many newer machines export one channel of 53c896 chip
+ * as SE, 50-pin HD. Also used for Multi-initiator SCSI clusters
+ * to set the SCSI Initiator ID.
+ */
+ get_pci_node_path(np->s.device, &hwpath);
+ if (pdc_get_initiator(&hwpath, &np->myaddr, &pdc_period, &np->maxwide, &scsi_mode))
+ {
+ if (scsi_mode >= 0) {
+ /* C3000 PDC reports period/mode */
+ SYM_SETUP_SCSI_DIFF = 0;
+ switch(scsi_mode) {
+ case 0: np->scsi_mode = SMODE_SE; break;
+ case 1: np->scsi_mode = SMODE_HVD; break;
+ case 2: np->scsi_mode = SMODE_LVD; break;
+ default: break;
+ }
+ }
+
+ period = (u32) pdc_period;
+ }
+#endif
+
if (period <= 250) np->minsync = 10;
else if (period <= 303) np->minsync = 11;
else if (period <= 500) np->minsync = 12;
@@ -862,7 +893,7 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
* In dual channel mode, contention occurs if internal cycles
* are used. Disable internal cycles.
*/
- if (np->device_id == PCI_ID_LSI53C1010 &&
+ if (np->device_id == PCI_ID_LSI53C1010_33 &&
np->revision_id < 0x1)
np->rv_ccntl0 |= DILS;
@@ -1362,17 +1393,17 @@ static struct sym_pci_chip sym_pci_dev_table[] = {
FE_WIDE|FE_ULTRA|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|
FE_RAM|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_LCKFRQ}
,
- {PCI_ID_LSI53C1010, 0x00, "1010-33", 6, 31, 7, 8,
+ {PCI_ID_LSI53C1010_33, 0x00, "1010-33", 6, 31, 7, 8,
FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
FE_C10}
,
- {PCI_ID_LSI53C1010, 0xff, "1010-33", 6, 31, 7, 8,
+ {PCI_ID_LSI53C1010_33, 0xff, "1010-33", 6, 31, 7, 8,
FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_CRC|
FE_C10|FE_U3EN}
,
- {PCI_ID_LSI53C1010_2, 0xff, "1010-66", 6, 31, 7, 8,
+ {PCI_ID_LSI53C1010_66, 0xff, "1010-66", 6, 31, 7, 8,
FE_WIDE|FE_ULTRA3|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFBC|FE_LDSTR|FE_PFEN|
FE_RAM|FE_RAM8K|FE_64BIT|FE_DAC|FE_IO256|FE_NOPM|FE_LEDC|FE_66MHZ|FE_CRC|
FE_C10|FE_U3EN}
@@ -1809,7 +1840,7 @@ void sym_start_up (hcb_p np, int reason)
/*
* For now, disable AIP generation on C1010-66.
*/
- if (np->device_id == PCI_ID_LSI53C1010_2)
+ if (np->device_id == PCI_ID_LSI53C1010_66)
OUTB (nc_aipcntl1, DISAIP);
/*
@@ -1819,7 +1850,7 @@ void sym_start_up (hcb_p np, int reason)
* that from SCRIPTS for each selection/reselection, but
* I just don't want. :)
*/
- if (np->device_id == PCI_ID_LSI53C1010 &&
+ if (np->device_id == PCI_ID_LSI53C1010_33 &&
np->revision_id < 1)
OUTB (nc_stest1, INB(nc_stest1) | 0x30);
diff --git a/drivers/scsi/sym53c8xx_2/sym_misc.h b/drivers/scsi/sym53c8xx_2/sym_misc.h
index 3a4b41f13907..2b01031c5283 100644
--- a/drivers/scsi/sym53c8xx_2/sym_misc.h
+++ b/drivers/scsi/sym53c8xx_2/sym_misc.h
@@ -77,23 +77,8 @@
* should be enough).
*/
-#if defined __i386__
-#define __READ_BARRIER() \
- __asm__ volatile("lock; addl $0,0(%%esp)": : :"memory")
-#define __WRITE_BARRIER() __asm__ volatile ("": : :"memory")
-#elif defined __powerpc__
-#define __READ_BARRIER() __asm__ volatile("eieio; sync" : : : "memory")
-#define __WRITE_BARRIER() __asm__ volatile("eieio; sync" : : : "memory")
-#elif defined __ia64__
-#define __READ_BARRIER() __asm__ volatile("mf.a; mf" : : : "memory")
-#define __WRITE_BARRIER() __asm__ volatile("mf.a; mf" : : : "memory")
-#elif defined __alpha__
-#define __READ_BARRIER() __asm__ volatile("mb": : :"memory")
-#define __WRITE_BARRIER() __asm__ volatile("mb": : :"memory")
-#else
-#define __READ_BARRIER() mb()
-#define __WRITE_BARRIER() mb()
-#endif
+#define __READ_BARRIER() rmb()
+#define __WRITE_BARRIER() wmb()
#ifndef MEMORY_READ_BARRIER
#define MEMORY_READ_BARRIER() __READ_BARRIER()
diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h
index 289e3f06bca9..13a68b562dda 100644
--- a/drivers/scsi/sym53c8xx_defs.h
+++ b/drivers/scsi/sym53c8xx_defs.h
@@ -259,17 +259,6 @@
#endif
/*
- * Vendor specific stuff
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT
-#define SCSI_NCR_SETUP_LED_PIN (1)
-#define SCSI_NCR_SETUP_DIFF_SUPPORT (4)
-#else
-#define SCSI_NCR_SETUP_LED_PIN (0)
-#define SCSI_NCR_SETUP_DIFF_SUPPORT (0)
-#endif
-
-/*
* Settle time after reset at boot-up
*/
#define SCSI_NCR_SETUP_SETTLE_TIME (2)
@@ -926,10 +915,10 @@ struct ncr_driver_setup {
SCSI_NCR_SETUP_DEFAULT_SYNC, \
0x00, \
7, \
- SCSI_NCR_SETUP_LED_PIN, \
+ 0, \
1, \
SCSI_NCR_SETUP_SETTLE_TIME, \
- SCSI_NCR_SETUP_DIFF_SUPPORT, \
+ 0, \
0, \
1, \
0, \
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index c85528623cfa..4205682ea286 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -798,7 +798,7 @@ int __init hiddev_init(void)
return usb_register(&hiddev_driver);
}
-void __exit hiddev_exit(void)
+void hiddev_exit(void)
{
usb_deregister(&hiddev_driver);
devfs_remove("usb/hid");
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index fb30277e2393..b580465fa08f 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -44,7 +44,6 @@
#include <linux/jiffies.h>
#include <linux/sysrq.h>
#include <linux/vmalloc.h>
-#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/io.h>
@@ -417,19 +416,8 @@ int show_stat(struct seq_file *p, void *v)
seq_printf(p, "intr %u", sum);
#if !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA)
-{
- static int last_irq = 0;
-
- for (i = last_irq; i < NR_IRQS; i++) {
- if (irq_desc[i].action) {
- if (i > last_irq)
- last_irq = i;
- }
- }
-
- for (i = 0; i <= last_irq; i++)
+ for (i = 0; i <= NR_IRQS; i++)
seq_printf(p, " %u", kstat_irqs(i));
-}
#endif
seq_printf(p,
diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h
index 11f174e6b3c3..48ba080c0794 100644
--- a/include/asm-sparc/termios.h
+++ b/include/asm-sparc/termios.h
@@ -73,6 +73,7 @@ struct winsize {
#define N_HCI 15 /* Bluetooth HCI UART */
#ifdef __KERNEL__
+#include <linux/module.h>
/*
* c_cc characters in the termio structure. Oh, how I love being
@@ -168,6 +169,9 @@ struct winsize {
0; \
})
+#define MODULE_ALIAS_LDISC(ldisc) \
+ MODULE_ALIAS("tty-ldisc-" __stringify(ldisc))
+
#endif /* __KERNEL__ */
#endif /* _SPARC_TERMIOS_H */
diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
index d29aa87ad90b..4e7fef518a25 100644
--- a/include/asm-sparc64/termios.h
+++ b/include/asm-sparc64/termios.h
@@ -73,6 +73,7 @@ struct winsize {
#define N_HCI 15 /* Bluetooth HCI UART */
#ifdef __KERNEL__
+#include <linux/module.h>
/*
* c_cc characters in the termio structure. Oh, how I love being
@@ -167,6 +168,9 @@ struct winsize {
0; \
})
+#define MODULE_ALIAS_LDISC(ldisc) \
+ MODULE_ALIAS("tty-ldisc-" __stringify(ldisc))
+
#endif /* __KERNEL__ */
#endif /* _SPARC64_TERMIOS_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 936f34c469dd..87ae270bf96c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1391,10 +1391,6 @@ extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count);
extern void simple_release_fs(struct vfsmount **mount, int *count);
-#ifdef CONFIG_BLK_DEV_INITRD
-extern unsigned int real_root_dev;
-#endif
-
extern int inode_change_ok(struct inode *, struct iattr *);
extern int inode_setattr(struct inode *, struct iattr *);
diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h
index dc6d8dd843b5..9e6d27476a74 100644
--- a/include/linux/hiddev.h
+++ b/include/linux/hiddev.h
@@ -207,7 +207,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value, struct pt_regs *regs);
void hiddev_report_event(struct hid_device *hid, struct hid_report *report);
int __init hiddev_init(void);
-void __exit hiddev_exit(void);
+void hiddev_exit(void);
#else
static inline int hiddev_connect(struct hid_device *hid) { return -1; }
static inline void hiddev_disconnect(struct hid_device *hid) { }
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 4664fd44a986..e7c50528e10e 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1218,7 +1218,6 @@ typedef struct ide_driver_s {
const char *version;
u8 media;
unsigned busy : 1;
- unsigned supports_dma : 1;
unsigned supports_dsc_overlap : 1;
int (*cleanup)(ide_drive_t *);
int (*shutdown)(ide_drive_t *);
diff --git a/include/linux/if_frad.h b/include/linux/if_frad.h
index 975aad03d762..3d9fc5d43803 100644
--- a/include/linux/if_frad.h
+++ b/include/linux/if_frad.h
@@ -155,9 +155,11 @@ struct frhdr
struct dlci_local
{
struct net_device_stats stats;
- struct net_device *slave;
+ struct net_device *master;
+ struct net_device *slave;
struct dlci_conf config;
int configured;
+ struct list_head list;
/* callback function */
void (*receive)(struct sk_buff *skb, struct net_device *);
diff --git a/include/linux/initrd.h b/include/linux/initrd.h
index 32452d53dac3..55289d261b4f 100644
--- a/include/linux/initrd.h
+++ b/include/linux/initrd.h
@@ -16,3 +16,5 @@ extern int initrd_below_start_ok;
/* free_initrd_mem always gets called with the next two as arguments.. */
extern unsigned long initrd_start, initrd_end;
extern void free_initrd_mem(unsigned long, unsigned long);
+
+extern unsigned int real_root_dev;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index dfc1aa47f35c..c99e53fed30e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -37,9 +37,6 @@
#ifdef __KERNEL__
#include <linux/config.h>
-#ifdef CONFIG_NET_PROFILE
-#include <net/profile.h>
-#endif
struct divert_blk;
struct vlan_group;
@@ -498,6 +495,7 @@ extern struct net_device loopback_dev; /* The loopback */
extern struct net_device *dev_base; /* All devices */
extern rwlock_t dev_base_lock; /* Device list lock */
+extern void probe_old_netdevs(void);
extern int netdev_boot_setup_add(char *name, struct ifmap *map);
extern int netdev_boot_setup_check(struct net_device *dev);
extern struct net_device *dev_getbyhwaddr(unsigned short type, char *hwaddr);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index c48edf4a551e..38c43d95a616 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -603,7 +603,8 @@ enum {
DEV_HWMON=2,
DEV_PARPORT=3,
DEV_RAID=4,
- DEV_MAC_HID=5
+ DEV_MAC_HID=5,
+ DEV_SCSI=6,
};
/* /proc/sys/dev/cdrom */
@@ -664,6 +665,11 @@ enum {
DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES=6
};
+/* /proc/sys/dev/scsi */
+enum {
+ DEV_SCSI_LOGGING_LEVEL=1,
+};
+
/* /proc/sys/abi */
enum
{
diff --git a/include/net/profile.h b/include/net/profile.h
deleted file mode 100644
index fd6a3b346990..000000000000
--- a/include/net/profile.h
+++ /dev/null
@@ -1,312 +0,0 @@
-#include <linux/config.h> /* for CONFIG_NET_PROFILE */
-#ifndef _NET_PROFILE_H_
-#define _NET_PROFILE_H_ 1
-
-#ifdef CONFIG_NET_PROFILE
-
-#include <linux/types.h>
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <asm/system.h>
-
-#ifdef CONFIG_X86_TSC
-#include <asm/msr.h>
-#endif
-
-struct net_profile_slot
-{
- char id[16];
- struct net_profile_slot *next;
- struct timeval entered;
- struct timeval accumulator;
- struct timeval irq;
- int hits;
- int active;
- int underflow;
-};
-
-extern atomic_t net_profile_active;
-extern struct timeval net_profile_adjust;
-extern void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved);
-
-#ifdef CONFIG_X86_TSC
-
-static inline void net_profile_stamp(struct timeval *pstamp)
-{
- rdtsc(pstamp->tv_usec, pstamp->tv_sec);
-}
-
-static inline void net_profile_accumulate(struct timeval *entered,
- struct timeval *leaved,
- struct timeval *acc)
-{
- __asm__ __volatile__ ("subl %2,%0\n\t"
- "sbbl %3,%1\n\t"
- "addl %4,%0\n\t"
- "adcl %5,%1\n\t"
- "subl net_profile_adjust+4,%0\n\t"
- "sbbl $0,%1\n\t"
- : "=r" (acc->tv_usec), "=r" (acc->tv_sec)
- : "g" (entered->tv_usec), "g" (entered->tv_sec),
- "g" (leaved->tv_usec), "g" (leaved->tv_sec),
- "0" (acc->tv_usec), "1" (acc->tv_sec));
-}
-
-static inline void net_profile_sub(struct timeval *sub,
- struct timeval *acc)
-{
- __asm__ __volatile__ ("subl %2,%0\n\t"
- "sbbl %3,%1\n\t"
- : "=r" (acc->tv_usec), "=r" (acc->tv_sec)
- : "g" (sub->tv_usec), "g" (sub->tv_sec),
- "0" (acc->tv_usec), "1" (acc->tv_sec));
-}
-
-static inline void net_profile_add(struct timeval *add,
- struct timeval *acc)
-{
- __asm__ __volatile__ ("addl %2,%0\n\t"
- "adcl %3,%1\n\t"
- : "=r" (acc->tv_usec), "=r" (acc->tv_sec)
- : "g" (add->tv_usec), "g" (add->tv_sec),
- "0" (acc->tv_usec), "1" (acc->tv_sec));
-}
-
-
-#elif defined (__alpha__)
-
-extern __u32 alpha_lo;
-extern long alpha_hi;
-
-/* On alpha cycle counter has only 32 bits :-( :-( */
-
-static inline void net_profile_stamp(struct timeval *pstamp)
-{
- __u32 result;
- __asm__ __volatile__ ("rpcc %0" : "r="(result));
- if (result <= alpha_lo)
- alpha_hi++;
- alpha_lo = result;
- pstamp->tv_sec = alpha_hi;
- pstamp->tv_usec = alpha_lo;
-}
-
-static inline void net_profile_accumulate(struct timeval *entered,
- struct timeval *leaved,
- struct timeval *acc)
-{
- time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec
- - net_profile_adjust.tv_usec;
- time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec;
-
- if (usecs >= 0x100000000L) {
- usecs -= 0x100000000L;
- secs++;
- } else if (usecs < -0x100000000L) {
- usecs += 0x200000000L;
- secs -= 2;
- } else if (usecs < 0) {
- usecs += 0x100000000L;
- secs--;
- }
- acc->tv_sec = secs;
- acc->tv_usec = usecs;
-}
-
-static inline void net_profile_sub(struct timeval *entered,
- struct timeval *leaved)
-{
- time_t usecs = leaved->tv_usec - entered->tv_usec;
- time_t secs = leaved->tv_sec - entered->tv_sec;
-
- if (usecs < 0) {
- usecs += 0x100000000L;
- secs--;
- }
- leaved->tv_sec = secs;
- leaved->tv_usec = usecs;
-}
-
-static inline void net_profile_add(struct timeval *entered, struct timeval *leaved)
-{
- time_t usecs = leaved->tv_usec + entered->tv_usec;
- time_t secs = leaved->tv_sec + entered->tv_sec;
-
- if (usecs >= 0x100000000L) {
- usecs -= 0x100000000L;
- secs++;
- }
- leaved->tv_sec = secs;
- leaved->tv_usec = usecs;
-}
-
-
-#else
-
-static inline void net_profile_stamp(struct timeval *pstamp)
-{
- /* Not "fast" counterpart! On architectures without
- cpu clock "fast" routine is absolutely useless in this
- situation. do_gettimeofday still says something on slow-slow-slow
- boxes, though it eats more cpu time than the subject of
- investigation :-) :-)
- */
- do_gettimeofday(pstamp);
-}
-
-static inline void net_profile_accumulate(struct timeval *entered,
- struct timeval *leaved,
- struct timeval *acc)
-{
- time_t usecs = acc->tv_usec + leaved->tv_usec - entered->tv_usec
- - net_profile_adjust.tv_usec;
- time_t secs = acc->tv_sec + leaved->tv_sec - entered->tv_sec;
-
- if (usecs >= 1000000) {
- usecs -= 1000000;
- secs++;
- } else if (usecs < -1000000) {
- usecs += 2000000;
- secs -= 2;
- } else if (usecs < 0) {
- usecs += 1000000;
- secs--;
- }
- acc->tv_sec = secs;
- acc->tv_usec = usecs;
-}
-
-static inline void net_profile_sub(struct timeval *entered,
- struct timeval *leaved)
-{
- time_t usecs = leaved->tv_usec - entered->tv_usec;
- time_t secs = leaved->tv_sec - entered->tv_sec;
-
- if (usecs < 0) {
- usecs += 1000000;
- secs--;
- }
- leaved->tv_sec = secs;
- leaved->tv_usec = usecs;
-}
-
-static inline void net_profile_add(struct timeval *entered, struct timeval *leaved)
-{
- time_t usecs = leaved->tv_usec + entered->tv_usec;
- time_t secs = leaved->tv_sec + entered->tv_sec;
-
- if (usecs >= 1000000) {
- usecs -= 1000000;
- secs++;
- }
- leaved->tv_sec = secs;
- leaved->tv_usec = usecs;
-}
-
-
-
-#endif
-
-static inline void net_profile_enter(struct net_profile_slot *s)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if (s->active++ == 0) {
- net_profile_stamp(&s->entered);
- atomic_inc(&net_profile_active);
- }
- restore_flags(flags);
-}
-
-static inline void net_profile_leave_irq(struct net_profile_slot *s)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if (--s->active <= 0) {
- if (s->active == 0) {
- struct timeval curr_pstamp;
- net_profile_stamp(&curr_pstamp);
- net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator);
- if (!atomic_dec_and_test(&net_profile_active))
- net_profile_irq_adjust(&s->entered, &curr_pstamp);
- } else {
- s->underflow++;
- }
- }
- s->hits++;
- restore_flags(flags);
-}
-
-static inline void net_profile_leave(struct net_profile_slot *s)
-{
- unsigned long flags;
- save_flags(flags);
- cli();
- if (--s->active <= 0) {
- if (s->active == 0) {
- struct timeval curr_pstamp;
- net_profile_stamp(&curr_pstamp);
- net_profile_accumulate(&s->entered, &curr_pstamp, &s->accumulator);
- atomic_dec(&net_profile_active);
- } else {
- s->underflow++;
- }
- }
- s->hits++;
- restore_flags(flags);
-}
-
-
-#define NET_PROFILE_ENTER(slot) net_profile_enter(&net_prof_##slot)
-#define NET_PROFILE_LEAVE(slot) net_profile_leave(&net_prof_##slot)
-#define NET_PROFILE_LEAVE_IRQ(slot) net_profile_leave_irq(&net_prof_##slot)
-
-#define NET_PROFILE_SKB_CLEAR(skb) ({ \
- skb->pstamp.tv_usec = 0; \
-})
-
-#define NET_PROFILE_SKB_INIT(skb) ({ \
- net_profile_stamp(&skb->pstamp); \
-})
-
-#define NET_PROFILE_SKB_PASSED(skb, slot) ({ \
- if (skb->pstamp.tv_usec) { \
- struct timeval cur_pstamp = skb->pstamp; \
- net_profile_stamp(&skb->pstamp); \
- net_profile_accumulate(&cur_pstamp, &skb->pstamp, &net_prof_##slot.accumulator); \
- net_prof_##slot.hits++; \
- }})
-
-#define NET_PROFILE_DECL(slot) \
- extern struct net_profile_slot net_prof_##slot;
-
-#define NET_PROFILE_DEFINE(slot) \
- struct net_profile_slot net_prof_##slot = { #slot, };
-
-#define NET_PROFILE_REGISTER(slot) net_profile_register(&net_prof_##slot)
-#define NET_PROFILE_UNREGISTER(slot) net_profile_unregister(&net_prof_##slot)
-
-extern int net_profile_init(void);
-extern int net_profile_register(struct net_profile_slot *);
-extern int net_profile_unregister(struct net_profile_slot *);
-
-#else
-
-#define NET_PROFILE_ENTER(slot) do { /* nothing */ } while(0)
-#define NET_PROFILE_LEAVE(slot) do { /* nothing */ } while(0)
-#define NET_PROFILE_LEAVE_IRQ(slot) do { /* nothing */ } while(0)
-#define NET_PROFILE_SKB_CLEAR(skb) do { /* nothing */ } while(0)
-#define NET_PROFILE_SKB_INIT(skb) do { /* nothing */ } while(0)
-#define NET_PROFILE_SKB_PASSED(skb, slot) do { /* nothing */ } while(0)
-#define NET_PROFILE_DECL(slot)
-#define NET_PROFILE_DEFINE(slot)
-#define NET_PROFILE_REGISTER(slot) do { /* nothing */ } while(0)
-#define NET_PROFILE_UNREGISTER(slot) do { /* nothing */ } while(0)
-
-#endif
-
-#endif
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 04b8f47837a9..17cac6fdaa34 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -74,8 +74,6 @@ struct scsi_device {
unsigned wdtr:1; /* Device supports WDTR messages */
unsigned ppr:1; /* Device supports PPR messages */
unsigned tagged_supported:1; /* Supports SCSI-II tagged queuing */
- unsigned tagged_queue:1;/* This is going away!!!! Look at simple_tags
- instead!!! Please fix your driver now!! */
unsigned simple_tags:1; /* simple queue tag messages are enabled */
unsigned ordered_tags:1;/* ordered queue tag messages are enabled */
unsigned single_lun:1; /* Indicates we should only allow I/O to
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
index d591d365c983..98719407d554 100644
--- a/include/scsi/scsi_request.h
+++ b/include/scsi/scsi_request.h
@@ -45,7 +45,7 @@ struct scsi_request {
level driver) of this request */
};
-extern struct scsi_request *scsi_allocate_request(struct scsi_device *);
+extern struct scsi_request *scsi_allocate_request(struct scsi_device *, int);
extern void scsi_release_request(struct scsi_request *);
extern void scsi_wait_req(struct scsi_request *, const void *cmnd,
void *buffer, unsigned bufflen,
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 142ccfcf835b..3180fa00d248 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -35,6 +35,7 @@
#include <linux/writeback.h>
#include <linux/hugetlb.h>
#include <linux/security.h>
+#include <linux/initrd.h>
#include <asm/uaccess.h>
#ifdef CONFIG_ROOT_NFS
diff --git a/mm/mremap.c b/mm/mremap.c
index d9180f18ad6c..0412a204cb69 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -420,7 +420,7 @@ unsigned long do_mremap(unsigned long addr,
if (flags & MREMAP_MAYMOVE) {
if (!(flags & MREMAP_FIXED)) {
unsigned long map_flags = 0;
- if (vma->vm_flags & VM_SHARED)
+ if (vma->vm_flags & VM_MAYSHARE)
map_flags |= MAP_SHARED;
new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
diff --git a/net/Kconfig b/net/Kconfig
index 4c3474604a0c..7d76574a9cc3 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -676,7 +676,6 @@ config NET_SCHED
source "net/sched/Kconfig"
-#bool 'Network code profiler' CONFIG_NET_PROFILE
endmenu
menu "Network testing"
diff --git a/net/atm/addr.c b/net/atm/addr.c
index 5974a1876116..459bdeed05f9 100644
--- a/net/atm/addr.c
+++ b/net/atm/addr.c
@@ -118,23 +118,24 @@ int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc *u_buf,int size)
{
unsigned long flags;
struct atm_dev_addr *walk;
- int total;
+ int total = 0, error;
+ struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
+
spin_lock_irqsave(&dev->lock, flags);
- total = 0;
- for (walk = dev->local; walk; walk = walk->next) {
+ for (walk = dev->local; walk; walk = walk->next)
total += sizeof(struct sockaddr_atmsvc);
- if (total > size) {
- spin_unlock_irqrestore(&dev->lock, flags);
- return -E2BIG;
- }
- if (copy_to_user(u_buf,&walk->addr,
- sizeof(struct sockaddr_atmsvc))) {
- spin_unlock_irqrestore(&dev->lock, flags);
- return -EFAULT;
- }
- u_buf++;
+ tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
+ if (!tmp_buf) {
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return -ENOMEM;
}
+ for (walk = dev->local; walk; walk = walk->next)
+ memcpy(tmp_bufp++, &walk->addr, sizeof(struct sockaddr_atmsvc));
spin_unlock_irqrestore(&dev->lock, flags);
- return total;
+ error = total > size ? -E2BIG : total;
+ if (copy_to_user(u_buf, tmp_buf, total < size ? total : size))
+ error = -EFAULT;
+ kfree(tmp_buf);
+ return error;
}
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index b1d5fff0d872..1292e56f3ce6 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -41,7 +41,6 @@
#include <linux/poll.h>
#include <linux/fcntl.h>
#include <linux/init.h>
-#include <linux/skbuff.h>
#include <linux/interrupt.h>
#include <linux/socket.h>
#include <linux/skbuff.h>
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 4b7c3315ff89..f62df6a7d153 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -1794,7 +1794,7 @@ static void *rfcomm_seq_next(struct seq_file *seq, void *e, loff_t *pos)
if (p->next != &s->dlcs)
return p->next;
- for (p = s->list.next; p != &session_list; p = p->next) {
+ list_for_each(p, &session_list) {
s = list_entry(p, struct rfcomm_session, list);
__list_for_each(pp, &s->dlcs) {
seq->private = s;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 04dc0898ad1c..99aa7e32a695 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -39,7 +39,6 @@
#include <linux/poll.h>
#include <linux/fcntl.h>
#include <linux/init.h>
-#include <linux/skbuff.h>
#include <linux/interrupt.h>
#include <linux/socket.h>
#include <linux/skbuff.h>
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index b1ef7c76663d..f277bd75de7a 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -41,7 +41,6 @@
#include <linux/poll.h>
#include <linux/fcntl.h>
#include <linux/init.h>
-#include <linux/skbuff.h>
#include <linux/interrupt.h>
#include <linux/socket.h>
#include <linux/skbuff.h>
diff --git a/net/core/Makefile b/net/core/Makefile
index 28ec942019e8..22e715cbdeb2 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -11,6 +11,5 @@ obj-y += flow.o dev.o ethtool.o net-sysfs.o dev_mcast.o dst.o \
obj-$(CONFIG_NETFILTER) += netfilter.o
obj-$(CONFIG_NET_DIVERT) += dv.o
-obj-$(CONFIG_NET_PROFILE) += profile.o
obj-$(CONFIG_NET_PKTGEN) += pktgen.o
obj-$(CONFIG_NET_RADIO) += wireless.o
diff --git a/net/core/dev.c b/net/core/dev.c
index fe8976f4e757..2cf887cee6d7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -99,7 +99,6 @@
#include <linux/divert.h>
#include <net/dst.h>
#include <net/pkt_sched.h>
-#include <net/profile.h>
#include <net/checksum.h>
#include <linux/highmem.h>
#include <linux/init.h>
@@ -128,9 +127,6 @@ extern int plip_init(void);
*/
#undef OFFLINE_SAMPLE
-NET_PROFILE_DEFINE(dev_queue_xmit)
-NET_PROFILE_DEFINE(softnet_process)
-
/*
* The list of packet types we will receive (as opposed to discard)
* and the routines to invoke.
@@ -2981,7 +2977,6 @@ int unregister_netdevice(struct net_device *dev)
*/
static int __init net_dev_init(void)
{
- struct net_device *dev, **dp;
int i, rc = -ENOMEM;
BUG_ON(!dev_boot_phase);
@@ -3016,88 +3011,15 @@ static int __init net_dev_init(void)
atomic_set(&queue->backlog_dev.refcnt, 1);
}
-#ifdef CONFIG_NET_PROFILE
- net_profile_init();
- NET_PROFILE_REGISTER(dev_queue_xmit);
- NET_PROFILE_REGISTER(softnet_process);
-#endif
-
#ifdef OFFLINE_SAMPLE
samp_timer.expires = jiffies + (10 * HZ);
add_timer(&samp_timer);
#endif
- /*
- * Add the devices.
- * If the call to dev->init fails, the dev is removed
- * from the chain disconnecting the device until the
- * next reboot.
- *
- * NB At boot phase networking is dead. No locking is required.
- * But we still preserve dev_base_lock for sanity.
- */
-
- dp = &dev_base;
- while ((dev = *dp) != NULL) {
- spin_lock_init(&dev->queue_lock);
- spin_lock_init(&dev->xmit_lock);
-#ifdef CONFIG_NET_FASTROUTE
- dev->fastpath_lock = RW_LOCK_UNLOCKED;
-#endif
- dev->xmit_lock_owner = -1;
- dev->iflink = -1;
- dev_hold(dev);
-
- /*
- * Allocate name. If the init() fails
- * the name will be reissued correctly.
- */
- if (strchr(dev->name, '%'))
- dev_alloc_name(dev, dev->name);
-
- /*
- * Check boot time settings for the device.
- */
- netdev_boot_setup_check(dev);
-
- if ( (dev->init && dev->init(dev)) ||
- netdev_register_sysfs(dev) ) {
- /*
- * It failed to come up. It will be unhooked later.
- * dev_alloc_name can now advance to next suitable
- * name that is checked next.
- */
- dp = &dev->next;
- } else {
- dp = &dev->next;
- dev->ifindex = dev_new_index();
- dev->reg_state = NETREG_REGISTERED;
- if (dev->iflink == -1)
- dev->iflink = dev->ifindex;
- if (!dev->rebuild_header)
- dev->rebuild_header = default_rebuild_header;
- dev_init_scheduler(dev);
- set_bit(__LINK_STATE_PRESENT, &dev->state);
- }
- }
-
- /*
- * Unhook devices that failed to come up
- */
- dp = &dev_base;
- while ((dev = *dp) != NULL) {
- if (dev->reg_state != NETREG_REGISTERED) {
- write_lock_bh(&dev_base_lock);
- *dp = dev->next;
- write_unlock_bh(&dev_base_lock);
- dev_put(dev);
- } else {
- dp = &dev->next;
- }
- }
-
dev_boot_phase = 0;
+ probe_old_netdevs();
+
open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL);
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index 958385890b79..ae21f8932e45 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -11,7 +11,6 @@
*
*/
-#include <linux/workqueue.h>
#include <linux/config.h>
#include <linux/netdevice.h>
#include <linux/if.h>
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
index ffb6a4471e85..07cbaf6b3c1e 100644
--- a/net/core/netfilter.c
+++ b/net/core/netfilter.c
@@ -101,7 +101,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg)
if (down_interruptible(&nf_sockopt_mutex) != 0)
return -EINTR;
- for (i = nf_sockopts.next; i != &nf_sockopts; i = i->next) {
+ list_for_each(i, &nf_sockopts) {
struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
if (ops->pf == reg->pf
&& (overlap(ops->set_optmin, ops->set_optmax,
@@ -296,7 +296,7 @@ static int nf_sockopt(struct sock *sk, int pf, int val,
if (down_interruptible(&nf_sockopt_mutex) != 0)
return -EINTR;
- for (i = nf_sockopts.next; i != &nf_sockopts; i = i->next) {
+ list_for_each(i, &nf_sockopts) {
ops = (struct nf_sockopt_ops *)i;
if (ops->pf == pf) {
if (get) {
diff --git a/net/core/profile.c b/net/core/profile.c
deleted file mode 100644
index 0caedda13842..000000000000
--- a/net/core/profile.c
+++ /dev/null
@@ -1,294 +0,0 @@
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/string.h>
-#include <linux/skbuff.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/ip.h>
-#include <linux/inet.h>
-#include <net/checksum.h>
-
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <net/profile.h>
-
-#ifdef CONFIG_NET_PROFILE
-
-atomic_t net_profile_active;
-struct timeval net_profile_adjust;
-
-NET_PROFILE_DEFINE(total);
-
-struct net_profile_slot *net_profile_chain = &net_prof_total;
-
-#ifdef __alpha__
-__u32 alpha_lo;
-long alpha_hi;
-
-static void alpha_tick(unsigned long);
-
-static struct timer_list alpha_timer = TIMER_INITIALIZER(alpha_tick, 0, 0);
-
-void alpha_tick(unsigned long dummy)
-{
- struct timeval dummy_stamp;
- net_profile_stamp(&dummy_stamp);
- alpha_timer.expires = jiffies + 4*HZ;
- add_timer(&alpha_timer);
-}
-
-#endif
-
-void net_profile_irq_adjust(struct timeval *entered, struct timeval* leaved)
-{
- struct net_profile_slot *s;
-
- net_profile_sub(entered, leaved);
- for (s = net_profile_chain; s; s = s->next) {
- if (s->active)
- net_profile_add(leaved, &s->irq);
- }
-}
-
-
-#ifdef CONFIG_PROC_FS
-static int profile_read_proc(char *buffer, char **start, off_t offset,
- int length, int *eof, void *data)
-{
- off_t pos=0;
- off_t begin=0;
- int len=0;
- struct net_profile_slot *s;
-
- len+= sprintf(buffer, "Slot Hits Hi Lo OnIrqHi OnIrqLo Ufl\n");
-
- if (offset == 0) {
- cli();
- net_prof_total.active = 1;
- atomic_inc(&net_profile_active);
- NET_PROFILE_LEAVE(total);
- sti();
- }
- for (s = net_profile_chain; s; s = s->next) {
- struct net_profile_slot tmp;
-
- cli();
- tmp = *s;
-
- /* Wrong, but pretty close to truth */
-
- s->accumulator.tv_sec = 0;
- s->accumulator.tv_usec = 0;
- s->irq.tv_sec = 0;
- s->irq.tv_usec = 0;
- s->hits = 0;
- s->underflow = 0;
- /* Repair active count, it is possible, only if code has a bug */
- if (s->active) {
- s->active = 0;
- atomic_dec(&net_profile_active);
- }
- sti();
-
- net_profile_sub(&tmp.irq, &tmp.accumulator);
-
- len += sprintf(buffer+len,"%-15s %-10d %-10ld %-10lu %-10lu %-10lu %d/%d",
- tmp.id,
- tmp.hits,
- tmp.accumulator.tv_sec,
- tmp.accumulator.tv_usec,
- tmp.irq.tv_sec,
- tmp.irq.tv_usec,
- tmp.underflow, tmp.active);
-
- buffer[len++]='\n';
-
- pos=begin+len;
- if(pos<offset) {
- len=0;
- begin=pos;
- }
- if(pos>offset+length)
- goto done;
- }
- *eof = 1;
-
-done:
- *start=buffer+(offset-begin);
- len-=(offset-begin);
- if(len>length)
- len=length;
- if (len < 0)
- len = 0;
- if (offset == 0) {
- cli();
- net_prof_total.active = 0;
- net_prof_total.hits = 0;
- net_profile_stamp(&net_prof_total.entered);
- sti();
- }
- return len;
-}
-#endif
-
-struct iphdr whitehole_iph;
-int whitehole_count;
-
-static int whitehole_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct net_device_stats *stats;
-
- stats = (struct net_device_stats *)dev->priv;
- stats->tx_packets++;
- stats->tx_bytes+=skb->len;
-
- dev_kfree_skb(skb);
- return 0;
-}
-
-static void whitehole_inject(unsigned long);
-int whitehole_init(struct net_device *dev);
-
-static struct timer_list whitehole_timer =
- TIMER_INITIALIZER(whitehole_inject, 0, 0);
-
-static struct net_device whitehole_dev = {
- .name = "whitehole",
- .init = whitehole_init,
-};
-
-static int whitehole_open(struct net_device *dev)
-{
- whitehole_count = 100000;
- whitehole_timer.expires = jiffies + 5*HZ;
- add_timer(&whitehole_timer);
- return 0;
-}
-
-static int whitehole_close(struct net_device *dev)
-{
- del_timer(&whitehole_timer);
- return 0;
-}
-
-static void whitehole_inject(unsigned long dummy)
-{
- struct net_device_stats *stats = (struct net_device_stats *)whitehole_dev.priv;
- extern int netdev_dropping;
-
- do {
- struct iphdr *iph;
- struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
- if (!skb)
- break;
- skb_reserve(skb, 32);
- iph = (struct iphdr*)skb_put(skb, sizeof(*iph));
- skb->mac.raw = ((u8*)iph) - 14;
- memcpy(iph, &whitehole_iph, sizeof(*iph));
- skb->protocol = __constant_htons(ETH_P_IP);
- skb->dev = &whitehole_dev;
- skb->pkt_type = PACKET_HOST;
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
- netif_rx(skb);
- whitehole_count--;
- } while (netdev_dropping == 0 && whitehole_count>0);
- if (whitehole_count > 0) {
- whitehole_timer.expires = jiffies + 1;
- add_timer(&whitehole_timer);
- }
-}
-
-static struct net_device_stats *whitehole_get_stats(struct net_device *dev)
-{
- struct net_device_stats *stats = (struct net_device_stats *) dev->priv;
- return stats;
-}
-
-int __init whitehole_init(struct net_device *dev)
-{
- dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOBUFS;
- memset(dev->priv, 0, sizeof(struct net_device_stats));
- dev->get_stats = whitehole_get_stats;
- dev->hard_start_xmit = whitehole_xmit;
- dev->open = whitehole_open;
- dev->stop = whitehole_close;
- ether_setup(dev);
- dev->tx_queue_len = 0;
- dev->flags |= IFF_NOARP;
- dev->flags &= ~(IFF_BROADCAST|IFF_MULTICAST);
- dev->iflink = 0;
- whitehole_iph.ihl = 5;
- whitehole_iph.version = 4;
- whitehole_iph.ttl = 2;
- whitehole_iph.saddr = in_aton("193.233.7.21");
- whitehole_iph.daddr = in_aton("193.233.7.10");
- whitehole_iph.tot_len = htons(20);
- whitehole_iph.check = ip_compute_csum((void *)&whitehole_iph, 20);
- return 0;
-}
-
-int net_profile_register(struct net_profile_slot *slot)
-{
- cli();
- slot->next = net_profile_chain;
- net_profile_chain = slot;
- sti();
- return 0;
-}
-
-int net_profile_unregister(struct net_profile_slot *slot)
-{
- struct net_profile_slot **sp, *s;
-
- for (sp = &net_profile_chain; (s = *sp) != NULL; sp = &s->next) {
- if (s == slot) {
- cli();
- *sp = s->next;
- sti();
- return 0;
- }
- }
- return -ESRCH;
-}
-
-
-int __init net_profile_init(void)
-{
- int i;
-
-#ifdef CONFIG_PROC_FS
- create_proc_read_entry("net/profile", 0, 0, profile_read_proc, NULL);
-#endif
-
- register_netdevice(&whitehole_dev);
-
- printk("Evaluating net profiler cost ...");
-#ifdef __alpha__
- alpha_tick(0);
-#endif
- for (i=0; i<1024; i++) {
- NET_PROFILE_ENTER(total);
- NET_PROFILE_LEAVE(total);
- }
- if (net_prof_total.accumulator.tv_sec) {
- printk(" too high!\n");
- } else {
- net_profile_adjust.tv_usec = net_prof_total.accumulator.tv_usec>>10;
- printk("%ld units\n", net_profile_adjust.tv_usec);
- }
- net_prof_total.hits = 0;
- net_profile_stamp(&net_prof_total.entered);
- return 0;
-}
-
-#endif
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 52a0c5f688ff..918505be8ea7 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -35,7 +35,6 @@
#include <linux/string.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
-#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/sysctl.h>
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index ac3aafd9aa82..166e3be72987 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -31,7 +31,6 @@
#include <linux/proc_fs.h>
#include <linux/timer.h>
#include <linux/swap.h>
-#include <linux/proc_fs.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index d6e5f3bcb7f4..6dc8fd2a065b 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -150,8 +150,7 @@ list_conntracks(char *buffer, char **start, off_t offset, int length)
}
/* Now iterate through expecteds. */
- for (e = ip_conntrack_expect_list.next;
- e != &ip_conntrack_expect_list; e = e->next) {
+ list_for_each(e, &ip_conntrack_expect_list) {
unsigned int last_len;
struct ip_conntrack_expect *expect
= (struct ip_conntrack_expect *)e;
@@ -319,7 +318,7 @@ int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
struct list_head *i;
WRITE_LOCK(&ip_conntrack_lock);
- for (i = protocol_list.next; i != &protocol_list; i = i->next) {
+ list_for_each(i, &protocol_list) {
if (((struct ip_conntrack_protocol *)i)->proto
== proto->proto) {
ret = -EBUSY;
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index a9f726b10a46..249c8e66f5aa 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -157,8 +157,8 @@ in_range(const struct ip_conntrack_tuple *tuple,
continue;
}
- if ((mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
- && proto->in_range(&newtuple, IP_NAT_MANIP_SRC,
+ if (!(mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
+ || proto->in_range(&newtuple, IP_NAT_MANIP_SRC,
&mr->range[i].min, &mr->range[i].max))
return 1;
}
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 75df6c8222bb..0e3028dcb176 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -50,7 +50,6 @@
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_helper.h>
-#include <linux/types.h>
#include <linux/ip.h>
#include <net/udp.h>
#include <asm/uaccess.h>
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 825ae9ffef36..bd014b74571f 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -271,7 +271,7 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto)
struct list_head *i;
WRITE_LOCK(&ip_nat_lock);
- for (i = protos.next; i != &protos; i = i->next) {
+ list_for_each(i, &protos) {
if (((struct ip_nat_protocol *)i)->protonum
== proto->protonum) {
ret = -EBUSY;
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 6374bdd52780..1398b8590dba 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -45,7 +45,6 @@
#include <linux/netlink.h>
#include <linux/netdevice.h>
#include <linux/mm.h>
-#include <linux/socket.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_ULOG.h>
#include <linux/netfilter_ipv4/lockhelp.h>
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 08c3a40a4bd2..1746eae040b3 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1349,64 +1349,65 @@ struct proto udp_prot = {
/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
-static __inline__ struct sock *udp_get_bucket(struct seq_file *seq, loff_t *pos)
+static struct sock *udp_get_first(struct seq_file *seq)
{
- int i;
struct sock *sk;
- struct hlist_node *node;
- loff_t l = *pos;
struct udp_iter_state *state = seq->private;
- for (; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
- i = 0;
+ for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
+ struct hlist_node *node;
sk_for_each(sk, node, &udp_hash[state->bucket]) {
- if (sk->sk_family != state->family) {
- ++i;
- continue;
- }
- if (l--) {
- ++i;
- continue;
- }
- *pos = i;
- goto out;
+ if (sk->sk_family == state->family)
+ goto found;
}
}
sk = NULL;
-out:
+found:
return sk;
}
+static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
+{
+ struct udp_iter_state *state = seq->private;
+
+ do {
+ sk = sk_next(sk);
+try_again:
+ ;
+ } while (sk && sk->sk_family != state->family);
+
+ if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
+ sk = sk_head(&udp_hash[state->bucket]);
+ goto try_again;
+ }
+ return sk;
+}
+
+static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos)
+{
+ struct sock *sk = udp_get_first(seq);
+
+ if (sk)
+ while(pos && (sk = udp_get_next(seq, sk)) != NULL)
+ --pos;
+ return pos ? NULL : sk;
+}
+
static void *udp_seq_start(struct seq_file *seq, loff_t *pos)
{
read_lock(&udp_hash_lock);
- return *pos ? udp_get_bucket(seq, pos) : (void *)1;
+ return *pos ? udp_get_idx(seq, *pos-1) : (void *)1;
}
static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct sock *sk;
- struct hlist_node *node;
- struct udp_iter_state *state;
-
- if (v == (void *)1) {
- sk = udp_get_bucket(seq, pos);
- goto out;
- }
-
- state = seq->private;
-
- sk = v;
- sk_for_each_continue(sk, node)
- if (sk->sk_family == state->family)
- goto out;
- if (++state->bucket >= UDP_HTABLE_SIZE)
- goto out;
+ if (v == (void *)1)
+ sk = udp_get_idx(seq, 0);
+ else
+ sk = udp_get_next(seq, v);
- *pos = 0;
- sk = udp_get_bucket(seq, pos);
-out:
++*pos;
return sk;
}
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c6246d0fc1d6..150089e25d2c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -57,7 +57,6 @@
#include <linux/delay.h>
#include <linux/notifier.h>
-#include <linux/proc_fs.h>
#include <net/sock.h>
#include <net/snmp.h>
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 6289170cb341..e55d83a6f14d 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -40,7 +40,6 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
-#include <linux/version.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 358b3f3f3d18..a97c931c5549 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -28,7 +28,6 @@
#include <linux/module.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
-#include <net/xfrm.h>
#include <net/ah.h>
#include <linux/crypto.h>
#include <linux/pfkeyv2.h>
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index fed773b5f439..3347859a1665 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -968,7 +968,7 @@ int netlink_post(int unit, struct sk_buff *skb)
#ifdef CONFIG_PROC_FS
static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos)
{
- int i;
+ long i;
struct sock *s;
struct hlist_node *node;
loff_t off = 0;
@@ -1002,7 +1002,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
s = sk_next(v);
if (!s) {
- int i = (int) seq->private;
+ long i = (long)seq->private;
while (++i < MAX_LINKS) {
s = sk_head(&nl_table[i]);
diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c
index ada78e6532ba..08df88fcd643 100644
--- a/net/rxrpc/sysctl.c
+++ b/net/rxrpc/sysctl.c
@@ -14,7 +14,6 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/sysctl.h>
-#include <linux/config.h>
#include <rxrpc/types.h>
#include <rxrpc/rxrpc.h>
#include <asm/errno.h>
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 4ba7f3d5c2e4..67a13170c6d7 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -20,7 +20,6 @@
#include <linux/proc_fs.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svcsock.h>
-#include <linux/init.h>
#define RPCDBG_FACILITY RPCDBG_MISC