diff options
| author | Patrick Mochel <mochel@osdl.org> | 2003-09-03 22:34:50 -0700 |
|---|---|---|
| committer | Patrick Mochel <mochel@osdl.org> | 2003-09-03 22:34:50 -0700 |
| commit | ed446fd17168dbbf2ff13c1871943f95fc055a49 (patch) | |
| tree | 50f035814350da82220e0551f99f9af0bbad86d8 | |
| parent | 29b12b99c0fd84b52974bbea7161fba8223fefa8 (diff) | |
| parent | 31412915d5d1de833892ac14d61db02ec8dce625 (diff) | |
Merge osdl.org:/home/mochel/src/kernel/linux-2.5-virgin
into osdl.org:/home/mochel/src/kernel/linux-2.5-core
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 = ð7_dev, - .init = ethif_probe, -}; -static struct net_device eth5_dev = { - .name = "eth%d", - .next = ð6_dev, - .init = ethif_probe, -}; -static struct net_device eth4_dev = { - .name = "eth%d", - .next = ð5_dev, - .init = ethif_probe, -}; -static struct net_device eth3_dev = { - .name = "eth%d", - .next = ð4_dev, - .init = ethif_probe, -}; -static struct net_device eth2_dev = { - .name = "eth%d", - .next = ð3_dev, - .init = ethif_probe, -}; -static struct net_device eth1_dev = { - .name = "eth%d", - .next = ð2_dev, - .init = ethif_probe, -}; -static struct net_device eth0_dev = { - .name = "eth%d", - .next = ð1_dev, - .init = ethif_probe, -}; - -#undef NEXT_DEV -#define NEXT_DEV (ð0_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 = <pc_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 = <dmabuf[800]; - if (!ltdmabuf) { printk(KERN_ERR "ltpc: mem alloc failed\n"); - return -1; + err = -ENOMEM; + goto out2; } + ltdmacbuf = <dmabuf[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 = <pc_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(<pc_timer); @@ -1221,8 +1199,23 @@ int __init ltpc_probe(struct net_device *dev) ltpc_timer.expires = jiffies + HZ/20; add_timer(<pc_timer); } + err = register_netdev(dev); + if (err) + goto out4; return 0; +out4: + del_timer_sync(<pc_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(<pc_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(<pc_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(<pc_timer); - while(del_timer(<pc_timer) && time_after(timeout, jiffies)) - { - add_timer(<pc_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 |
