summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-03-17 18:47:47 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2002-03-17 18:47:47 -0800
commit5326862d17d4ff78c79fbe72df50b16f37812782 (patch)
treec2ae5e215c153e486c0da99f4242f0863c2dd606
parenta2f1b7bc189cb5fc32a76dfe89d160849a1b600a (diff)
parentcfc632c815d9fab4c0f9f22487bbb6da38da6d3a (diff)
Automerge
-rw-r--r--arch/ppc/kernel/align.c2
-rw-r--r--arch/ppc/kernel/prom_init.c16
-rw-r--r--arch/ppc/platforms/pmac_feature.c10
-rw-r--r--drivers/pci/pci.c55
-rw-r--r--drivers/usb/Config.help1
-rw-r--r--drivers/usb/catc.c291
-rw-r--r--drivers/usb/hid-core.c72
-rw-r--r--drivers/usb/hid.h3
-rw-r--r--drivers/usb/hiddev.c116
-rw-r--r--drivers/usb/printer.c603
-rw-r--r--drivers/usb/serial/cyberjack.c8
-rw-r--r--drivers/usb/serial/digi_acceleport.c14
-rw-r--r--drivers/usb/serial/empeg.c8
-rw-r--r--drivers/usb/serial/ftdi_sio.c4
-rw-r--r--drivers/usb/serial/io_edgeport.c18
-rw-r--r--drivers/usb/serial/ipaq.c4
-rw-r--r--drivers/usb/serial/ir-usb.c4
-rw-r--r--drivers/usb/serial/keyspan.c14
-rw-r--r--drivers/usb/serial/keyspan_pda.c4
-rw-r--r--drivers/usb/serial/kl5kusb105.c8
-rw-r--r--drivers/usb/serial/mct_u232.c2
-rw-r--r--drivers/usb/serial/omninet.c4
-rw-r--r--drivers/usb/serial/pl2303.c8
-rw-r--r--drivers/usb/serial/usbserial.c4
-rw-r--r--drivers/usb/serial/visor.c10
-rw-r--r--drivers/usb/serial/whiteheat.c2
-rw-r--r--fs/filesystems.c223
-rw-r--r--fs/isofs/dir.c17
-rw-r--r--fs/isofs/inode.c157
-rw-r--r--fs/isofs/joliet.c4
-rw-r--r--fs/isofs/namei.c13
-rw-r--r--fs/isofs/rock.c26
-rw-r--r--fs/super.c225
-rw-r--r--fs/udf/super.c9
-rw-r--r--fs/udf/udf_sb.h6
-rw-r--r--fs/udf/udfdecl.h4
-rw-r--r--include/asm-ppc/siginfo.h2
-rw-r--r--include/asm-ppc/thread_info.h9
-rw-r--r--include/linux/fs.h4
-rw-r--r--include/linux/hiddev.h12
-rw-r--r--include/linux/if_wanpipe.h1
-rw-r--r--include/linux/iso_fs.h7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c2
-rw-r--r--net/wanrouter/af_wanpipe.c55
44 files changed, 1310 insertions, 751 deletions
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index 0f8dbd1cb585..ed023aace203 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -28,7 +28,7 @@ struct aligninfo {
#define OPCD(inst) (((inst) & 0xFC000000) >> 26)
#define RS(inst) (((inst) & 0x03E00000) >> 21)
#define RA(inst) (((inst) & 0x001F0000) >> 16)
-#define IS_DFORM(code) ((code) >= 32 && (code) <= 47)
+#define IS_DFORM(code) ((code) >= 32 && (code) <= 55)
#endif
#define INVALID { 0, 0 }
diff --git a/arch/ppc/kernel/prom_init.c b/arch/ppc/kernel/prom_init.c
index fea41427aa29..96f43675dae8 100644
--- a/arch/ppc/kernel/prom_init.c
+++ b/arch/ppc/kernel/prom_init.c
@@ -50,7 +50,7 @@
#define FB_MAX 8
#endif
-#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
+#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
struct prom_args {
const char *service;
@@ -376,7 +376,7 @@ try_again:
}
}
- return ALIGN(mem);
+ return ALIGNUL(mem);
}
/* This function will enable the early boot text when doing OF booting. This
@@ -457,7 +457,7 @@ copy_device_tree(unsigned long mem_start, unsigned long mem_end)
prom_exit();
}
allnextp = &allnodes;
- mem_start = ALIGN(mem_start);
+ mem_start = ALIGNUL(mem_start);
new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);
*allnextp = 0;
return new_start;
@@ -501,7 +501,7 @@ inspect_node(phandle node, struct device_node *dad,
if ((int) call_prom("nextprop", 3, 1, node, prev_name,
namep) <= 0)
break;
- mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
+ mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
prev_name = namep;
valp = (unsigned char *) mem_start;
pp->value = PTRUNRELOC(valp);
@@ -514,7 +514,7 @@ inspect_node(phandle node, struct device_node *dad,
if (pp->length > MAX_PROPERTY_LENGTH)
continue; /* ignore this property */
#endif
- mem_start = ALIGN(mem_start + pp->length);
+ mem_start = ALIGNUL(mem_start + pp->length);
*prev_propp = PTRUNRELOC(pp);
prev_propp = &pp->next;
}
@@ -526,7 +526,7 @@ inspect_node(phandle node, struct device_node *dad,
namep = (char *) (pp + 1);
pp->name = PTRUNRELOC(namep);
strcpy(namep, "linux,phandle");
- mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);
+ mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
pp->value = (unsigned char *) PTRUNRELOC(&np->node);
pp->length = sizeof(np->node);
}
@@ -538,7 +538,7 @@ inspect_node(phandle node, struct device_node *dad,
if (l >= 0) {
np->full_name = PTRUNRELOC((char *) mem_start);
*(char *)(mem_start + l) = 0;
- mem_start = ALIGN(mem_start + l + 1);
+ mem_start = ALIGNUL(mem_start + l + 1);
}
/* do all our children */
@@ -741,7 +741,7 @@ prom_init(int r3, int r4, prom_entry pp)
*d = 0;
call_prom("canon", 3, 1, p, d, 1<<20);
bootdevice = PTRUNRELOC(d);
- mem = ALIGN(mem + strlen(d) + 1);
+ mem = ALIGNUL(mem + strlen(d) + 1);
}
prom_instantiate_rtas();
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
index 3a930be3e77d..ee134a1b84cf 100644
--- a/arch/ppc/platforms/pmac_feature.c
+++ b/arch/ppc/platforms/pmac_feature.c
@@ -400,13 +400,17 @@ heathrow_modem_enable(struct device_node* node, int param, int value)
LOCK(flags);
MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
+ UNLOCK(flags);
+ mdelay(250);
+ LOCK(flags);
MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
+ UNLOCK(flags);
+ mdelay(250);
+ LOCK(flags);
MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
+ UNLOCK(flags);
}
return 0;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 890ca713c999..a8fa051737f8 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1710,7 +1710,6 @@ struct pci_pool { /* the pool */
spinlock_t lock;
size_t blocks_per_page;
size_t size;
- int flags;
struct pci_dev *dev;
size_t allocation;
char name [32];
@@ -1727,8 +1726,6 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
#define POOL_POISON_BYTE 0xa7
-// #define CONFIG_PCIPOOL_DEBUG
-
/**
* pci_pool_create - Creates a pool of pci consistent memory blocks, for dma.
@@ -1737,7 +1734,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
* @size: size of the blocks in this pool.
* @align: alignment requirement for blocks; must be a power of two
* @allocation: returned blocks won't cross this boundary (or zero)
- * @flags: SLAB_* flags (not all are supported).
+ * @mem_flags: SLAB_* flags.
*
* Returns a pci allocation pool with the requested characteristics, or
* null if one can't be created. Given one of these pools, pci_pool_alloc()
@@ -1753,7 +1750,7 @@ struct pci_page { /* cacheable header for 'allocation' bytes */
*/
struct pci_pool *
pci_pool_create (const char *name, struct pci_dev *pdev,
- size_t size, size_t align, size_t allocation, int flags)
+ size_t size, size_t align, size_t allocation, int mem_flags)
{
struct pci_pool *retval;
@@ -1777,13 +1774,9 @@ pci_pool_create (const char *name, struct pci_dev *pdev,
} else if (allocation < size)
return 0;
- if (!(retval = kmalloc (sizeof *retval, flags)))
+ if (!(retval = kmalloc (sizeof *retval, mem_flags)))
return retval;
-#ifdef CONFIG_PCIPOOL_DEBUG
- flags |= SLAB_POISON;
-#endif
-
strncpy (retval->name, name, sizeof retval->name);
retval->name [sizeof retval->name - 1] = 0;
@@ -1791,17 +1784,10 @@ pci_pool_create (const char *name, struct pci_dev *pdev,
INIT_LIST_HEAD (&retval->page_list);
spin_lock_init (&retval->lock);
retval->size = size;
- retval->flags = flags;
retval->allocation = allocation;
retval->blocks_per_page = allocation / size;
init_waitqueue_head (&retval->waitq);
-#ifdef CONFIG_PCIPOOL_DEBUG
- printk (KERN_DEBUG "pcipool create %s/%s size %d, %d/page (%d alloc)\n",
- pdev ? pdev->slot_name : NULL, retval->name, size,
- retval->blocks_per_page, allocation);
-#endif
-
return retval;
}
@@ -1824,8 +1810,9 @@ pool_alloc_page (struct pci_pool *pool, int mem_flags)
&page->dma);
if (page->vaddr) {
memset (page->bitmap, 0xff, mapsize); // bit set == free
- if (pool->flags & SLAB_POISON)
- memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+#ifdef CONFIG_DEBUG_SLAB
+ memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+#endif
list_add (&page->page_list, &pool->page_list);
} else {
kfree (page);
@@ -1851,8 +1838,9 @@ pool_free_page (struct pci_pool *pool, struct pci_page *page)
{
dma_addr_t dma = page->dma;
- if (pool->flags & SLAB_POISON)
- memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+#ifdef CONFIG_DEBUG_SLAB
+ memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
+#endif
pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma);
list_del (&page->page_list);
kfree (page);
@@ -1871,12 +1859,6 @@ pci_pool_destroy (struct pci_pool *pool)
{
unsigned long flags;
-#ifdef CONFIG_PCIPOOL_DEBUG
- printk (KERN_DEBUG "pcipool destroy %s/%s\n",
- pool->dev ? pool->dev->slot_name : NULL,
- pool->name);
-#endif
-
spin_lock_irqsave (&pool->lock, flags);
while (!list_empty (&pool->page_list)) {
struct pci_page *page;
@@ -2010,30 +1992,27 @@ pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma)
pool->name, vaddr, (unsigned long) dma);
return;
}
-#ifdef CONFIG_PCIPOOL_DEBUG
- if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
- printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n",
- pool->dev ? pool->dev->slot_name : NULL,
- pool->name, vaddr, (unsigned long) dma);
- return;
- }
-#endif
block = dma - page->dma;
block /= pool->size;
map = block / BITS_PER_LONG;
block %= BITS_PER_LONG;
-#ifdef CONFIG_PCIPOOL_DEBUG
+#ifdef CONFIG_DEBUG_SLAB
+ if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
+ printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n",
+ pool->dev ? pool->dev->slot_name : NULL,
+ pool->name, vaddr, (unsigned long) dma);
+ return;
+ }
if (page->bitmap [map] & (1UL << block)) {
printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n",
pool->dev ? pool->dev->slot_name : NULL,
pool->name, dma);
return;
}
+ memset (vaddr, POOL_POISON_BYTE, pool->size);
#endif
- if (pool->flags & SLAB_POISON)
- memset (vaddr, POOL_POISON_BYTE, pool->size);
spin_lock_irqsave (&pool->lock, flags);
set_bit (block, &page->bitmap [map]);
diff --git a/drivers/usb/Config.help b/drivers/usb/Config.help
index f76202f07b7a..28a88d96a72c 100644
--- a/drivers/usb/Config.help
+++ b/drivers/usb/Config.help
@@ -382,6 +382,7 @@ CONFIG_USB_KAWETH
CONFIG_USB_CATC
Say Y if you want to use one of the following 10Mbps USB Ethernet
device based on the EL1210A chip. Supported devices are:
+ Belkin F5U011
Belkin F5U111
CATC NetMate
CATC NetMate II
diff --git a/drivers/usb/catc.c b/drivers/usb/catc.c
index 3bea97a3c04e..37a300d9e2d0 100644
--- a/drivers/usb/catc.c
+++ b/drivers/usb/catc.c
@@ -7,6 +7,9 @@
*
* Based on the work of
* Donald Becker
+ *
+ * Old chipset support added by Simon Evans <spse@secret.org.uk> 2002
+ * - adds support for Belkin F5U011
*/
/*
@@ -70,6 +73,7 @@ MODULE_LICENSE("GPL");
#define RX_MAX_BURST 15 /* Max packets per rx buffer (> 0, < 16) */
#define TX_MAX_BURST 15 /* Max full sized packets per tx buffer (> 0) */
#define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */
+#define RX_PKT_SZ 1600 /* Max size of receive packet for F5U011 */
/*
* Control requests.
@@ -80,6 +84,7 @@ enum control_requests {
GetMac = 0xf2,
Reset = 0xf4,
SetMac = 0xf5,
+ SetRxMode = 0xf5, /* F5U011 only */
WriteROM = 0xf8,
SetReg = 0xfa,
GetReg = 0xfb,
@@ -127,6 +132,7 @@ enum rx_filter_bits {
RxForceOK = 0x04,
RxMultiCast = 0x08,
RxPromisc = 0x10,
+ AltRxPromisc = 0x20, /* F5U011 uses different bit */
};
enum led_values {
@@ -137,6 +143,12 @@ enum led_values {
LEDLink = 0x08,
};
+enum link_status {
+ LinkNoChange = 0,
+ LinkGood = 1,
+ LinkBad = 2
+};
+
/*
* The catc struct.
*/
@@ -180,6 +192,10 @@ struct catc {
} ctrl_queue[CTRL_QUEUE];
struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb;
+
+ u8 is_f5u011; /* Set if device is an F5U011 */
+ u8 rxmode[2]; /* Used for F5U011 */
+ atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */
};
/*
@@ -193,6 +209,10 @@ struct catc {
#define catc_write_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size)
#define catc_read_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_IN, ReadMem, 0, addr, buf, size)
+#define f5u011_rxmode(catc, rxmode) catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2)
+#define f5u011_rxmode_async(catc, rxmode) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL)
+#define f5u011_mchash_async(catc, hash) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL)
+
#define catc_set_reg_async(catc, reg, val) catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL)
#define catc_get_reg_async(catc, reg, cb) catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb)
#define catc_write_mem_async(catc, addr, buf, size) catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL)
@@ -206,9 +226,12 @@ static void catc_rx_done(struct urb *urb)
struct catc *catc = urb->context;
u8 *pkt_start = urb->transfer_buffer;
struct sk_buff *skb;
- int pkt_len;
+ int pkt_len, pkt_offset = 0;
- clear_bit(RX_RUNNING, &catc->flags);
+ if (!catc->is_f5u011) {
+ clear_bit(RX_RUNNING, &catc->flags);
+ pkt_offset = 2;
+ }
if (urb->status) {
dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
@@ -216,19 +239,22 @@ static void catc_rx_done(struct urb *urb)
}
do {
- pkt_len = le16_to_cpup((u16*)pkt_start);
-
- if (pkt_len > urb->actual_length) {
- catc->stats.rx_length_errors++;
- catc->stats.rx_errors++;
- break;
+ if(!catc->is_f5u011) {
+ pkt_len = le16_to_cpup((u16*)pkt_start);
+ if (pkt_len > urb->actual_length) {
+ catc->stats.rx_length_errors++;
+ catc->stats.rx_errors++;
+ break;
+ }
+ } else {
+ pkt_len = urb->actual_length;
}
if (!(skb = dev_alloc_skb(pkt_len)))
return;
skb->dev = catc->netdev;
- eth_copy_and_sum(skb, pkt_start + 2, pkt_len, 0);
+ eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, catc->netdev);
@@ -237,11 +263,28 @@ static void catc_rx_done(struct urb *urb)
catc->stats.rx_packets++;
catc->stats.rx_bytes += pkt_len;
+ /* F5U011 only does one packet per RX */
+ if (catc->is_f5u011)
+ break;
pkt_start += (((pkt_len + 1) >> 6) + 1) << 6;
} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
catc->netdev->last_rx = jiffies;
+
+ if (catc->is_f5u011) {
+ if (atomic_read(&catc->recq_sz)) {
+ int status;
+ atomic_dec(&catc->recq_sz);
+ dbg("getting extra packet");
+ urb->dev = catc->usbdev;
+ if ((status = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
+ dbg("submit(rx_urb) status %d", status);
+ }
+ } else {
+ clear_bit(RX_RUNNING, &catc->flags);
+ }
+ }
}
static void catc_irq_done(struct urb *urb)
@@ -249,29 +292,48 @@ static void catc_irq_done(struct urb *urb)
struct catc *catc = urb->context;
u8 *data = urb->transfer_buffer;
int status;
+ unsigned int hasdata = 0, linksts = LinkNoChange;
+
+ if (!catc->is_f5u011) {
+ hasdata = data[1] & 0x80;
+ if (data[1] & 0x40)
+ linksts = LinkGood;
+ else if (data[1] & 0x20)
+ linksts = LinkBad;
+ } else {
+ hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
+ if (data[0] == 0x90)
+ linksts = LinkGood;
+ else if (data[0] == 0xA0)
+ linksts = LinkBad;
+ }
if (urb->status) {
dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
return;
}
- if ((data[1] & 0x80) && !test_and_set_bit(RX_RUNNING, &catc->flags)) {
- catc->rx_urb->dev = catc->usbdev;
- if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
- err("submit(rx_urb) status %d", status);
- return;
- }
- }
-
- if (data[1] & 0x40) {
+ if (linksts == LinkGood) {
netif_carrier_on(catc->netdev);
dbg("link ok");
}
- if (data[1] & 0x20) {
+ if (linksts == LinkBad) {
netif_carrier_off(catc->netdev);
dbg("link bad");
}
+
+ if (hasdata) {
+ if (test_and_set_bit(RX_RUNNING, &catc->flags)) {
+ if (catc->is_f5u011)
+ atomic_inc(&catc->recq_sz);
+ } else {
+ catc->rx_urb->dev = catc->usbdev;
+ if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
+ err("submit(rx_urb) status %d", status);
+ }
+ }
+ }
}
/*
@@ -282,6 +344,9 @@ static void catc_tx_run(struct catc *catc)
{
int status;
+ if (catc->is_f5u011)
+ catc->tx_ptr = (catc->tx_ptr + 63) & ~63;
+
catc->tx_urb->transfer_buffer_length = catc->tx_ptr;
catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
catc->tx_urb->dev = catc->usbdev;
@@ -338,14 +403,15 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
- *((u16*)tx_buf) = cpu_to_le16((u16)skb->len);
+ *((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
memcpy(tx_buf + 2, skb->data, skb->len);
catc->tx_ptr += skb->len + 2;
if (!test_and_set_bit(TX_RUNNING, &catc->flags))
catc_tx_run(catc);
- if (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2)))
+ if ((catc->is_f5u011 && catc->tx_ptr)
+ || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
netif_stop_queue(netdev);
spin_unlock_irqrestore(&catc->tx_lock, flags);
@@ -554,17 +620,32 @@ static void catc_set_multicast_list(struct net_device *netdev)
if (netdev->flags & IFF_PROMISC) {
memset(catc->multicast, 0xff, 64);
- rx |= RxPromisc;
+ rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc;
}
- if (netdev->flags & IFF_ALLMULTI)
+ if (netdev->flags & IFF_ALLMULTI) {
memset(catc->multicast, 0xff, 64);
-
- for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next)
- catc_multicast(mc->dmi_addr, catc->multicast);
-
- catc_set_reg_async(catc, RxUnit, rx);
- catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
+ } else {
+ for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) {
+ u32 crc = ether_crc_le(6, mc->dmi_addr);
+ if (!catc->is_f5u011) {
+ catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
+ } else {
+ catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7);
+ }
+ }
+ }
+ if (!catc->is_f5u011) {
+ catc_set_reg_async(catc, RxUnit, rx);
+ catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
+ } else {
+ f5u011_mchash_async(catc, catc->multicast);
+ if (catc->rxmode[0] != rx) {
+ catc->rxmode[0] = rx;
+ dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0], catc->rxmode[1]);
+ f5u011_rxmode_async(catc, catc->rxmode);
+ }
+ }
}
/*
@@ -591,6 +672,29 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
return -EFAULT;
return 0;
}
+
+ /* get settings */
+ case ETHTOOL_GSET:
+ if (catc->is_f5u011) {
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET,
+ SUPPORTED_10baseT_Half | SUPPORTED_TP,
+ ADVERTISED_10baseT_Half | ADVERTISED_TP,
+ SPEED_10,
+ DUPLEX_HALF,
+ PORT_TP,
+ 0,
+ XCVR_INTERNAL,
+ AUTONEG_DISABLE,
+ 1,
+ 1
+ };
+ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+ return -EFAULT;
+ return 0;
+ } else {
+ return -EOPNOTSUPP;
+ }
+
/* get link status */
case ETHTOOL_GLINK: {
struct ethtool_value edata = {ETHTOOL_GLINK};
@@ -632,7 +736,8 @@ static int catc_open(struct net_device *netdev)
netif_start_queue(netdev);
- mod_timer(&catc->timer, jiffies + STATS_UPDATE);
+ if (!catc->is_f5u011)
+ mod_timer(&catc->timer, jiffies + STATS_UPDATE);
return 0;
}
@@ -643,7 +748,8 @@ static int catc_stop(struct net_device *netdev)
netif_stop_queue(netdev);
- del_timer_sync(&catc->timer);
+ if (!catc->is_f5u011)
+ del_timer_sync(&catc->timer);
usb_unlink_urb(catc->rx_urb);
usb_unlink_urb(catc->tx_urb);
@@ -662,7 +768,7 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
struct net_device *netdev;
struct catc *catc;
u8 broadcast[6];
- int i;
+ int i, pktsz;
if (usb_set_interface(usbdev, ifnum, 1)) {
err("Can't set altsetting 1.");
@@ -670,9 +776,16 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
}
catc = kmalloc(sizeof(struct catc), GFP_KERNEL);
+ if (!catc)
+ return NULL;
+
memset(catc, 0, sizeof(struct catc));
netdev = init_etherdev(0, 0);
+ if (!netdev) {
+ kfree(catc);
+ return NULL;
+ }
netdev->open = catc_open;
netdev->hard_start_xmit = catc_hard_start_xmit;
@@ -701,9 +814,26 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) {
err("No free urbs available.");
+ if (catc->ctrl_urb) usb_free_urb(catc->ctrl_urb);
+ if (catc->tx_urb) usb_free_urb(catc->tx_urb);
+ if (catc->rx_urb) usb_free_urb(catc->rx_urb);
+ if (catc->irq_urb) usb_free_urb(catc->irq_urb);
+ kfree(netdev);
+ kfree(catc);
return NULL;
}
+ /* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
+ if (usbdev->descriptor.idVendor == 0x0423 && usbdev->descriptor.idProduct == 0xa &&
+ catc->usbdev->descriptor.bcdDevice == 0x0130 ) {
+ dbg("Testing for f5u011");
+ catc->is_f5u011 = 1;
+ atomic_set(&catc->recq_sz, 0);
+ pktsz = RX_PKT_SZ;
+ } else {
+ pktsz = RX_MAX_BURST * (PKT_SZ + 2);
+ }
+
FILL_CONTROL_URB(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
NULL, NULL, 0, catc_ctrl_done, catc);
@@ -711,20 +841,21 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
NULL, 0, catc_tx_done, catc);
FILL_BULK_URB(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
- catc->rx_buf, RX_MAX_BURST * (PKT_SZ + 2), catc_rx_done, catc);
+ catc->rx_buf, pktsz, catc_rx_done, catc);
FILL_INT_URB(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
catc->irq_buf, 2, catc_irq_done, catc, 1);
- dbg("Checking memory size\n");
-
- i = 0x12345678;
- catc_write_mem(catc, 0x7a80, &i, 4);
- i = 0x87654321;
- catc_write_mem(catc, 0xfa80, &i, 4);
- catc_read_mem(catc, 0x7a80, &i, 4);
+ if (!catc->is_f5u011) {
+ dbg("Checking memory size\n");
- switch (i) {
+ i = 0x12345678;
+ catc_write_mem(catc, 0x7a80, &i, 4);
+ i = 0x87654321;
+ catc_write_mem(catc, 0xfa80, &i, 4);
+ catc_read_mem(catc, 0x7a80, &i, 4);
+
+ switch (i) {
case 0x12345678:
catc_set_reg(catc, TxBufCount, 8);
catc_set_reg(catc, RxBufCount, 32);
@@ -737,44 +868,52 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
catc_set_reg(catc, RxBufCount, 16);
dbg("32k Memory\n");
break;
+ }
+
+ dbg("Getting MAC from SEEROM.");
+
+ catc_get_mac(catc, netdev->dev_addr);
+
+ dbg("Setting MAC into registers.");
+
+ for (i = 0; i < 6; i++)
+ catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
+
+ dbg("Filling the multicast list.");
+
+ memset(broadcast, 0xff, 6);
+ catc_multicast(broadcast, catc->multicast);
+ catc_multicast(netdev->dev_addr, catc->multicast);
+ catc_write_mem(catc, 0xfa80, catc->multicast, 64);
+
+ dbg("Clearing error counters.");
+
+ for (i = 0; i < 8; i++)
+ catc_set_reg(catc, EthStats + i, 0);
+ catc->last_stats = jiffies;
+
+ dbg("Enabling.");
+
+ catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
+ catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
+ catc_set_reg(catc, LEDCtrl, LEDLink);
+ catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
+ } else {
+ dbg("Performing reset\n");
+ catc_reset(catc);
+ catc_get_mac(catc, netdev->dev_addr);
+
+ dbg("Setting RX Mode");
+ catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;
+ catc->rxmode[1] = 0;
+ f5u011_rxmode(catc, catc->rxmode);
}
-
- dbg("Getting MAC from SEEROM.");
-
- catc_get_mac(catc, netdev->dev_addr);
-
- dbg("Setting MAC into registers.");
-
- for (i = 0; i < 6; i++)
- catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
-
- dbg("Filling the multicast list.");
-
- memset(broadcast, 0xff, 8);
- catc_multicast(broadcast, catc->multicast);
- catc_multicast(netdev->dev_addr, catc->multicast);
- catc_write_mem(catc, 0xfa80, catc->multicast, 64);
-
- dbg("Clearing error counters.");
-
- for (i = 0; i < 8; i++)
- catc_set_reg(catc, EthStats + i, 0);
- catc->last_stats = jiffies;
-
- dbg("Enabling.");
-
- catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
- catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
- catc_set_reg(catc, LEDCtrl, LEDLink);
- catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
-
dbg("Init done.");
-
- printk(KERN_INFO "%s: CATC EL1210A NetMate USB Ethernet at usb%d:%d.%d, ",
- netdev->name, usbdev->bus->busnum, usbdev->devnum, ifnum);
+ printk(KERN_INFO "%s: %s USB Ethernet at usb%d:%d.%d, ",
+ netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",
+ usbdev->bus->busnum, usbdev->devnum, ifnum);
for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);
printk("%2.2x.\n", netdev->dev_addr[i]);
-
return catc;
}
@@ -795,7 +934,7 @@ static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr)
*/
static struct usb_device_id catc_id_table [] = {
- { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate */
+ { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate, Belkin F5U011 */
{ USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */
{ USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */
{ }
diff --git a/drivers/usb/hid-core.c b/drivers/usb/hid-core.c
index 5b3f0c64273e..0bb17425bc39 100644
--- a/drivers/usb/hid-core.c
+++ b/drivers/usb/hid-core.c
@@ -110,10 +110,11 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+ values * sizeof(unsigned));
- report->field[report->maxfield++] = field;
+ report->field[report->maxfield] = field;
field->usage = (struct hid_usage *)(field + 1);
field->value = (unsigned *)(field->usage + usages);
field->report = report;
+ field->index = report->maxfield++;
return field;
}
@@ -741,8 +742,20 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_hid_event(hid, field, usage, value);
#ifdef CONFIG_USB_HIDDEV
- if (hid->claimed & HID_CLAIMED_HIDDEV)
- hiddev_hid_event(hid, usage->hid, value);
+ if (hid->claimed & HID_CLAIMED_HIDDEV) {
+ struct hiddev_usage_ref uref;
+ unsigned type = field->report_type;
+ uref.report_type =
+ (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
+ ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
+ ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+ uref.report_id = field->report->id;
+ uref.field_index = field->index;
+ uref.usage_index = (usage - field->usage);
+ uref.usage_code = usage->hid;
+ uref.value = value;
+ hiddev_hid_event(hid, &uref);
+ }
#endif
}
@@ -839,6 +852,21 @@ static int hid_input_report(int type, struct urb *urb)
return -1;
}
+#ifdef CONFIG_USB_HIDDEV
+ /* Notify listeners that a report has been received */
+ if (hid->claimed & HID_CLAIMED_HIDDEV) {
+ struct hiddev_usage_ref uref;
+ memset(&uref, 0, sizeof(uref));
+ uref.report_type =
+ (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
+ ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
+ ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+ uref.report_id = report->id;
+ uref.field_index = HID_FIELD_INDEX_NONE;
+ hiddev_hid_event(hid, &uref);
+ }
+#endif
+
size = ((report->size - 1) >> 3) + 1;
if (len < size) {
@@ -1096,6 +1124,9 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
int head;
unsigned long flags;
+ if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
+ return;
+
if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
spin_lock_irqsave(&hid->outlock, flags);
@@ -1238,18 +1269,27 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_POWERMATE 0x0410
#define USB_DEVICE_ID_SOUNDKNOB 0x04AA
+#define USB_VENDOR_ID_ATEN 0x0557
+#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
+#define USB_DEVICE_ID_ATEN_CS124U 0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
+
struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
+ unsigned quirks;
} hid_blacklist[] = {
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS },
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1},
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2},
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3},
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4},
- { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE },
- { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
{ 0, 0 }
};
@@ -1258,13 +1298,17 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
struct hid_descriptor *hdesc;
struct hid_device *hid;
- unsigned rsize = 0;
+ unsigned quirks = 0, rsize = 0;
char *buf;
int n;
for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
- (hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL;
+ (hid_blacklist[n].idProduct == dev->descriptor.idProduct))
+ quirks = hid_blacklist[n].quirks;
+
+ if (quirks & HID_QUIRK_IGNORE)
+ return NULL;
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
@@ -1302,6 +1346,8 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
}
}
+ hid->quirks = quirks;
+
for (n = 0; n < interface->bNumEndpoints; n++) {
struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
diff --git a/drivers/usb/hid.h b/drivers/usb/hid.h
index 77a656f2bcc9..ed72dc6acfd1 100644
--- a/drivers/usb/hid.h
+++ b/drivers/usb/hid.h
@@ -203,6 +203,8 @@ struct hid_item {
#define HID_QUIRK_INVERT 0x01
#define HID_QUIRK_NOTOUCH 0x02
+#define HID_QUIRK_IGNORE 0x04
+#define HID_QUIRK_NOGET 0x08
/*
* This is the global enviroment of the parser. This information is
@@ -276,6 +278,7 @@ struct hid_field {
__s32 unit_exponent;
unsigned unit;
struct hid_report *report; /* associated report */
+ unsigned index; /* index into report->field[] */
};
#define HID_MAX_FIELDS 64
diff --git a/drivers/usb/hiddev.c b/drivers/usb/hiddev.c
index 886a30825a92..5d4029259899 100644
--- a/drivers/usb/hiddev.c
+++ b/drivers/usb/hiddev.c
@@ -50,9 +50,10 @@ struct hiddev {
};
struct hiddev_list {
- struct hiddev_event buffer[HIDDEV_BUFFER_SIZE];
+ struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE];
int head;
int tail;
+ unsigned flags;
struct fasync_struct *fasync;
struct hiddev *hiddev;
struct hiddev_list *next;
@@ -146,17 +147,19 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
* This is where hid.c calls into hiddev to pass an event that occurred over
* the interrupt pipe
*/
-void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value)
+void hiddev_hid_event(struct hid_device *hid, struct hiddev_usage_ref *uref)
{
struct hiddev *hiddev = hid->hiddev;
struct hiddev_list *list = hiddev->list;
while (list) {
- list->buffer[list->head].hid = usage;
- list->buffer[list->head].value = value;
- list->head = (list->head + 1) & (HIDDEV_BUFFER_SIZE - 1);
-
- kill_fasync(&list->fasync, SIGIO, POLL_IN);
+ if (uref->field_index != HID_FIELD_INDEX_NONE ||
+ (list->flags & HIDDEV_FLAG_REPORT) != 0) {
+ list->buffer[list->head] = *uref;
+ list->head = (list->head + 1) &
+ (HIDDEV_BUFFER_SIZE - 1);
+ kill_fasync(&list->fasync, SIGIO, POLL_IN);
+ }
list = list->next;
}
@@ -257,43 +260,67 @@ static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
{
DECLARE_WAITQUEUE(wait, current);
struct hiddev_list *list = file->private_data;
+ int event_size;
int retval = 0;
- if (list->head == list->tail) {
-
- add_wait_queue(&list->hiddev->wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
+ event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
+ sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
- while (list->head == list->tail) {
+ if (count < event_size) return 0;
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- if (!list->hiddev->exist) {
- retval = -EIO;
- break;
+ while (retval == 0) {
+ if (list->head == list->tail) {
+ add_wait_queue(&list->hiddev->wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (list->head == list->tail) {
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (!list->hiddev->exist) {
+ retval = -EIO;
+ break;
+ }
+
+ schedule();
}
- schedule();
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&list->hiddev->wait, &wait);
}
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&list->hiddev->wait, &wait);
- }
-
- if (retval)
- return retval;
+ if (retval)
+ return retval;
+
+
+ while (list->head != list->tail &&
+ retval + event_size <= count) {
+ if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
+ if (list->buffer[list->tail].field_index !=
+ HID_FIELD_INDEX_NONE) {
+ struct hiddev_event event;
+ event.hid = list->buffer[list->tail].usage_code;
+ event.value = list->buffer[list->tail].value;
+ if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
+ return -EFAULT;
+ retval += sizeof(struct hiddev_event);
+ }
+ } else {
+ if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
+ (list->flags & HIDDEV_FLAG_REPORT) != 0) {
+ if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
+ return -EFAULT;
+ retval += sizeof(struct hiddev_usage_ref);
+ }
+ }
+ list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
+ }
- while (list->head != list->tail && retval + sizeof(struct hiddev_event) <= count) {
- if (copy_to_user(buffer + retval, list->buffer + list->tail,
- sizeof(struct hiddev_event))) return -EFAULT;
- list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
- retval += sizeof(struct hiddev_event);
}
return retval;
@@ -358,6 +385,25 @@ static int hiddev_ioctl(struct inode *inode, struct file *file,
return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
}
+ case HIDIOCGFLAG:
+ return put_user(list->flags, (int *) arg);
+
+ case HIDIOCSFLAG:
+ {
+ int newflags;
+ if (get_user(newflags, (int *) arg))
+ return -EFAULT;
+
+ if ((newflags & ~HIDDEV_FLAGS) != 0 ||
+ ((newflags & HIDDEV_FLAG_REPORT) != 0 &&
+ (newflags & HIDDEV_FLAG_UREF) == 0))
+ return -EINVAL;
+
+ list->flags = newflags;
+
+ return 0;
+ }
+
case HIDIOCGSTRING:
{
int idx, len;
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index 6025a0176103..00ea80dfca00 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -1,10 +1,12 @@
/*
- * printer.c Version 0.8
+ * printer.c Version 0.12
*
* Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
* Copyright (c) 2000 Randy Dunlap <randy.dunlap@intel.com>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
+ # Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com>
+ # Copyright (c) 2001 David Paschal <paschal@rcsis.com>
*
* USB Printer Device Class driver for USB printers and printer cables
*
@@ -17,10 +19,12 @@
* v0.4 - fixes in unidirectional mode
* v0.5 - add DEVICE_ID string support
* v0.6 - never time out
- * v0.7 - fixed bulk-IN read and poll (David Paschal, paschal@rcsis.com)
+ * v0.7 - fixed bulk-IN read and poll (David Paschal)
* v0.8 - add devfs support
* v0.9 - fix unplug-while-open paths
* v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
+ * v0.11 - add proto_bias option (Pete Zaitcev)
+ * v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
*/
/*
@@ -55,16 +59,36 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.10"
-#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap"
+#define DRIVER_VERSION "v0.12"
+#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
#define DRIVER_DESC "USB Printer Device Class driver"
#define USBLP_BUF_SIZE 8192
#define DEVICE_ID_SIZE 1024
-#define IOCNR_GET_DEVICE_ID 1
-#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) /* get device_id string */
+/* ioctls: */
#define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
+#define IOCNR_GET_DEVICE_ID 1
+#define IOCNR_GET_PROTOCOLS 2
+#define IOCNR_SET_PROTOCOL 3
+#define IOCNR_HP_SET_CHANNEL 4
+#define IOCNR_GET_BUS_ADDRESS 5
+#define IOCNR_GET_VID_PID 6
+/* Get device_id string: */
+#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
+/* The following ioctls were added for http://hpoj.sourceforge.net: */
+/* Get two-int array:
+ * [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
+ * [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */
+#define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len)
+/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */
+#define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0)
+/* Set channel number (HP Vendor-specific command): */
+#define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0)
+/* Get two-int array: [0]=bus number, [1]=device address: */
+#define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
+/* Get two-int array: [0]=vendor ID, [1]=product ID: */
+#define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
/*
* A DEVICE_ID string may include the printer's serial number.
@@ -78,26 +102,40 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
* USB Printer Requests
*/
-#define USBLP_REQ_GET_ID 0x00
-#define USBLP_REQ_GET_STATUS 0x01
-#define USBLP_REQ_RESET 0x02
+#define USBLP_REQ_GET_ID 0x00
+#define USBLP_REQ_GET_STATUS 0x01
+#define USBLP_REQ_RESET 0x02
+#define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST 0x00 /* HP Vendor-specific */
#define USBLP_MINORS 16
#define USBLP_MINOR_BASE 0
#define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */
+#define USBLP_FIRST_PROTOCOL 1
+#define USBLP_LAST_PROTOCOL 3
+#define USBLP_MAX_PROTOCOLS (USBLP_LAST_PROTOCOL+1)
+
struct usblp {
struct usb_device *dev; /* USB device */
devfs_handle_t devfs; /* devfs device */
struct semaphore sem; /* locks this struct, especially "dev" */
+ char *buf; /* writeurb->transfer_buffer */
struct urb *readurb, *writeurb; /* The urbs */
wait_queue_head_t wait; /* Zzzzz ... */
int readcount; /* Counter for reads */
int ifnum; /* Interface number */
+ /* Alternate-setting numbers and endpoints for each protocol
+ * (7/1/{index=1,2,3}) that the device supports: */
+ struct {
+ int alt_setting;
+ struct usb_endpoint_descriptor *epwrite;
+ struct usb_endpoint_descriptor *epread;
+ } protocol[USBLP_MAX_PROTOCOLS];
+ int current_protocol;
int minor; /* minor number of device */
int wcomplete; /* writing is completed */
- int rcomplete; /* reading is completed */
+ int rcomplete; /* reading is completed */
unsigned int quirks; /* quirks flags */
unsigned char used; /* True if open */
unsigned char bidir; /* interface is bidirectional */
@@ -105,6 +143,35 @@ struct usblp {
/* first 2 bytes are (big-endian) length */
};
+#ifdef DEBUG
+static void usblp_dump(struct usblp *usblp) {
+ int p;
+
+ dbg("usblp=0x%p", usblp);
+ dbg("dev=0x%p", usblp->dev);
+ dbg("devfs=0x%p", usblp->devfs);
+ dbg("buf=0x%p", usblp->buf);
+ dbg("readcount=%d", usblp->readcount);
+ dbg("ifnum=%d", usblp->ifnum);
+ for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
+ dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
+ dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
+ dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
+ }
+ dbg("current_protocol=%d", usblp->current_protocol);
+ dbg("minor=%d", usblp->minor);
+ dbg("wcomplete=%d", usblp->wcomplete);
+ dbg("rcomplete=%d", usblp->rcomplete);
+ dbg("quirks=%d", usblp->quirks);
+ dbg("used=%d", usblp->used);
+ dbg("bidir=%d", usblp->bidir);
+ dbg("device_id_string=\"%s\"",
+ usblp->device_id_string ?
+ usblp->device_id_string + 2 :
+ (unsigned char *)"(null)");
+}
+#endif
+
extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
static struct usblp *usblp_table[USBLP_MINORS];
@@ -126,29 +193,45 @@ static struct quirk_printer_struct quirk_printers[] = {
{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
+ { 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
{ 0, 0 }
};
+static int usblp_select_alts(struct usblp *usblp);
+static int usblp_set_protocol(struct usblp *usblp, int protocol);
+static int usblp_cache_device_id_string(struct usblp *usblp);
+
+
/*
* Functions for usblp control messages.
*/
-static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, int value, void *buf, int len)
+static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len)
{
int retval = usb_control_msg(usblp->dev,
dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
- request, USB_TYPE_CLASS | dir | recip, value, usblp->ifnum, buf, len, HZ * 5);
+ request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT);
dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
request, !!dir, recip, value, len, retval);
return retval < 0 ? retval : 0;
}
#define usblp_read_status(usblp, status)\
- usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
+ usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
#define usblp_get_id(usblp, config, id, maxlen)\
- usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
+ usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
#define usblp_reset(usblp)\
- usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
+ usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
+
+#define usblp_hp_channel_change_request(usblp, channel, buffer) \
+ usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1)
+
+/*
+ * See the description for usblp_select_alts() below for the usage
+ * explanation. Look into your /proc/bus/usb/devices and dmesg in
+ * case of any trouble.
+ */
+static int proto_bias = -1;
/*
* URB callback.
@@ -276,7 +359,7 @@ static void usblp_cleanup (struct usblp *usblp)
{
devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL;
- info ("usblp%d: removed", usblp->minor);
+ info("usblp%d: removed", usblp->minor);
kfree (usblp->writeurb->transfer_buffer);
kfree (usblp->device_id_string);
@@ -285,6 +368,13 @@ static void usblp_cleanup (struct usblp *usblp)
kfree (usblp);
}
+static void usblp_unlink_urbs(struct usblp *usblp)
+{
+ usb_unlink_urb(usblp->writeurb);
+ if (usblp->bidir)
+ usb_unlink_urb(usblp->readurb);
+}
+
static int usblp_release(struct inode *inode, struct file *file)
{
struct usblp *usblp = file->private_data;
@@ -293,9 +383,7 @@ static int usblp_release(struct inode *inode, struct file *file)
lock_kernel();
usblp->used = 0;
if (usblp->dev) {
- if (usblp->bidir)
- usb_unlink_urb(usblp->readurb);
- usb_unlink_urb(usblp->writeurb);
+ usblp_unlink_urbs(usblp);
up(&usblp->sem);
} else /* finish cleanup from disconnect */
usblp_cleanup (usblp);
@@ -315,8 +403,9 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct usblp *usblp = file->private_data;
- int length, err;
- unsigned char status;
+ int length, err, i;
+ unsigned char status, newChannel;
+ int twoints[2];
int retval = 0;
down (&usblp->sem);
@@ -335,32 +424,128 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
goto done;
}
- err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
+ length = usblp_cache_device_id_string(usblp);
+ if (length < 0) {
+ retval = length;
+ goto done;
+ }
+ if (length > _IOC_SIZE(cmd))
+ length = _IOC_SIZE(cmd); /* truncate */
+
+ if (copy_to_user((unsigned char *) arg,
+ usblp->device_id_string,
+ (unsigned long) length)) {
+ retval = -EFAULT;
+ goto done;
+ }
+
+ break;
+
+ case IOCNR_GET_PROTOCOLS:
+ if (_IOC_DIR(cmd) != _IOC_READ ||
+ _IOC_SIZE(cmd) < sizeof(twoints)) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+ twoints[0] = usblp->current_protocol;
+ twoints[1] = 0;
+ for (i = USBLP_FIRST_PROTOCOL;
+ i <= USBLP_LAST_PROTOCOL; i++) {
+ if (usblp->protocol[i].alt_setting >= 0)
+ twoints[1] |= (1<<i);
+ }
+
+ if (copy_to_user((unsigned char *)arg,
+ (unsigned char *)twoints,
+ sizeof(twoints))) {
+ retval = -EFAULT;
+ goto done;
+ }
+
+ break;
+
+ case IOCNR_SET_PROTOCOL:
+ if (_IOC_DIR(cmd) != _IOC_WRITE) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+#ifdef DEBUG
+ if (arg == -10) {
+ usblp_dump(usblp);
+ break;
+ }
+#endif
+
+ usblp_unlink_urbs(usblp);
+ retval = usblp_set_protocol(usblp, arg);
+ if (retval < 0) {
+ usblp_set_protocol(usblp,
+ usblp->current_protocol);
+ }
+ break;
+
+ case IOCNR_HP_SET_CHANNEL:
+ if (_IOC_DIR(cmd) != _IOC_WRITE ||
+ usblp->dev->descriptor.idVendor != 0x03F0 ||
+ usblp->quirks & USBLP_QUIRK_BIDIR) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+ err = usblp_hp_channel_change_request(usblp,
+ arg, &newChannel);
if (err < 0) {
- dbg ("usblp%d: error = %d reading IEEE-1284 Device ID string",
+ err("usblp%d: error = %d setting "
+ "HP channel",
usblp->minor, err);
- usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
retval = -EIO;
goto done;
}
- length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
- if (length < DEVICE_ID_SIZE)
- usblp->device_id_string[length] = '\0';
- else
- usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
+ dbg("usblp%d requested/got HP channel %ld/%d",
+ usblp->minor, arg, newChannel);
+ break;
- dbg ("usblp%d Device ID string [%d/max %d]='%s'",
- usblp->minor, length, _IOC_SIZE(cmd), &usblp->device_id_string[2]);
+ case IOCNR_GET_BUS_ADDRESS:
+ if (_IOC_DIR(cmd) != _IOC_READ ||
+ _IOC_SIZE(cmd) < sizeof(twoints)) {
+ retval = -EINVAL;
+ goto done;
+ }
- if (length > _IOC_SIZE(cmd)) length = _IOC_SIZE(cmd); /* truncate */
+ twoints[0] = usblp->dev->bus->busnum;
+ twoints[1] = usblp->dev->devnum;
+ if (copy_to_user((unsigned char *)arg,
+ (unsigned char *)twoints,
+ sizeof(twoints))) {
+ retval = -EFAULT;
+ goto done;
+ }
- if (copy_to_user((unsigned char *) arg,
- usblp->device_id_string, (unsigned long) length)) {
+ dbg("usblp%d is bus=%d, device=%d",
+ usblp->minor, twoints[0], twoints[1]);
+ break;
+
+ case IOCNR_GET_VID_PID:
+ if (_IOC_DIR(cmd) != _IOC_READ ||
+ _IOC_SIZE(cmd) < sizeof(twoints)) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+ twoints[0] = usblp->dev->descriptor.idVendor;
+ twoints[1] = usblp->dev->descriptor.idProduct;
+ if (copy_to_user((unsigned char *)arg,
+ (unsigned char *)twoints,
+ sizeof(twoints))) {
retval = -EFAULT;
goto done;
}
+ dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
+ usblp->minor, twoints[0], twoints[1]);
break;
default:
@@ -593,155 +778,268 @@ static struct file_operations usblp_fops = {
static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
- struct usb_interface_descriptor *interface;
- struct usb_endpoint_descriptor *epread, *epwrite;
- struct usblp *usblp;
- int minor, i, bidir = 0, quirks;
- int alts = dev->actconfig->interface[ifnum].act_altsetting;
- int length, err;
- char *buf;
+ struct usblp *usblp = 0;
+ int protocol;
char name[6];
- /* If a bidirectional interface exists, use it. */
- for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) {
-
- interface = &dev->actconfig->interface[ifnum].altsetting[i];
-
- if (interface->bInterfaceClass != 7 || interface->bInterfaceSubClass != 1 ||
- interface->bInterfaceProtocol < 1 || interface->bInterfaceProtocol > 3 ||
- (interface->bInterfaceProtocol > 1 && interface->bNumEndpoints < 2))
- continue;
-
- if (interface->bInterfaceProtocol > 1) {
- bidir = 1;
- alts = i;
- break;
- }
- }
-
- interface = &dev->actconfig->interface[ifnum].altsetting[alts];
- if (usb_set_interface(dev, ifnum, alts))
- err("can't set desired altsetting %d on interface %d", alts, ifnum);
-
- epwrite = interface->endpoint + 0;
- epread = bidir ? interface->endpoint + 1 : NULL;
-
- if ((epwrite->bEndpointAddress & 0x80) == 0x80) {
- if (interface->bNumEndpoints == 1)
- return NULL;
- epwrite = interface->endpoint + 1;
- epread = bidir ? interface->endpoint + 0 : NULL;
- }
-
- if ((epwrite->bEndpointAddress & 0x80) == 0x80)
- return NULL;
-
- if (bidir && (epread->bEndpointAddress & 0x80) != 0x80)
- return NULL;
-
- for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++);
- if (usblp_table[minor]) {
- err("no more free usblp devices");
- return NULL;
- }
-
+ /* Malloc and start initializing usblp structure so we can use it
+ * directly. */
if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
- err("out of memory");
- return NULL;
+ err("out of memory for usblp");
+ goto abort;
}
memset(usblp, 0, sizeof(struct usblp));
- init_MUTEX (&usblp->sem);
-
- /* lookup quirks for this printer */
- quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
-
- if (bidir && (quirks & USBLP_QUIRK_BIDIR)) {
- bidir = 0;
- epread = NULL;
- info ("Disabling reads from problem bidirectional printer on usblp%d",
- minor);
- }
-
usblp->dev = dev;
+ init_MUTEX (&usblp->sem);
+ init_waitqueue_head(&usblp->wait);
usblp->ifnum = ifnum;
- usblp->minor = minor;
- usblp->bidir = bidir;
- usblp->quirks = quirks;
- init_waitqueue_head(&usblp->wait);
+ /* Look for a free usblp_table entry. */
+ while (usblp_table[usblp->minor]) {
+ usblp->minor++;
+ if (usblp->minor >= USBLP_MINORS) {
+ err("no more free usblp devices");
+ goto abort;
+ }
+ }
usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->writeurb) {
err("out of memory");
- kfree(usblp);
- return NULL;
+ goto abort;
}
usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->readurb) {
err("out of memory");
- usb_free_urb(usblp->writeurb);
- kfree(usblp);
- return NULL;
+ goto abort;
}
- if (!(buf = kmalloc(USBLP_BUF_SIZE * (bidir ? 2 : 1), GFP_KERNEL))) {
- err("out of memory");
- usb_free_urb(usblp->writeurb);
- usb_free_urb(usblp->readurb);
- kfree(usblp);
- return NULL;
+ /* Malloc device ID string buffer to the largest expected length,
+ * since we can re-query it on an ioctl and a dynamic string
+ * could change in length. */
+ if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
+ err("out of memory for device_id_string");
+ goto abort;
}
- if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
- err("out of memory");
- usb_free_urb(usblp->writeurb);
- usb_free_urb(usblp->readurb);
- kfree(usblp);
- kfree(buf);
- return NULL;
+ /* Malloc write/read buffers in one chunk. We somewhat wastefully
+ * malloc both regardless of bidirectionality, because the
+ * alternate setting can be changed later via an ioctl. */
+ if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
+ err("out of memory for buf");
+ goto abort;
}
- FILL_BULK_URB(usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
- buf, 0, usblp_bulk_write, usblp);
+ /* Lookup quirks for this printer. */
+ usblp->quirks = usblp_quirks(
+ dev->descriptor.idVendor,
+ dev->descriptor.idProduct);
+
+ /* Analyze and pick initial alternate settings and endpoints. */
+ protocol = usblp_select_alts(usblp);
+ if (protocol < 0) {
+ dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
+ dev->descriptor.idVendor,
+ dev->descriptor.idProduct);
+ goto abort;
+ }
- if (bidir)
- FILL_BULK_URB(usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
- buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk_read, usblp);
+ /* Setup the selected alternate setting and endpoints. */
+ if (usblp_set_protocol(usblp, protocol) < 0)
+ goto abort;
- /* Get the device_id string if possible. FIXME: Could make this kmalloc(length). */
- err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
- if (err >= 0) {
- length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
- if (length < DEVICE_ID_SIZE)
- usblp->device_id_string[length] = '\0';
- else
- usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
- dbg ("usblp%d Device ID string [%d]=%s",
- minor, length, &usblp->device_id_string[2]);
- }
- else {
- err ("usblp%d: error = %d reading IEEE-1284 Device ID string",
- minor, err);
- usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
- }
+ /* Retrieve and store the device ID string. */
+ usblp_cache_device_id_string(usblp);
#ifdef DEBUG
usblp_check_status(usblp, 0);
#endif
- sprintf(name, "lp%d", minor);
-
- /* if we have devfs, create with perms=660 */
+ /* If we have devfs, create with perms=660. */
+ sprintf(name, "lp%d", usblp->minor);
usblp->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
- USBLP_MINOR_BASE + minor,
+ USBLP_MINOR_BASE + usblp->minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &usblp_fops, NULL);
- info("usblp%d: USB %sdirectional printer dev %d if %d alt %d",
- minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
+ info("usblp%d: USB %sdirectional printer dev %d "
+ "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
+ usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, ifnum,
+ usblp->protocol[usblp->current_protocol].alt_setting,
+ usblp->current_protocol, usblp->dev->descriptor.idVendor,
+ usblp->dev->descriptor.idProduct);
- return usblp_table[minor] = usblp;
+ return usblp_table[usblp->minor] = usblp;
+
+abort:
+ if (usblp) {
+ usb_free_urb(usblp->writeurb);
+ usb_free_urb(usblp->readurb);
+ if (usblp->buf) kfree(usblp->buf);
+ if (usblp->device_id_string) kfree(usblp->device_id_string);
+ kfree(usblp);
+ }
+ return NULL;
+}
+
+/*
+ * We are a "new" style driver with usb_device_id table,
+ * but our requirements are too intricate for simple match to handle.
+ *
+ * The "proto_bias" option may be used to specify the preferred protocol
+ * for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3). If the device
+ * supports the preferred protocol, then we bind to it.
+ *
+ * The best interface for us is 7/1/2, because it is compatible
+ * with a stream of characters. If we find it, we bind to it.
+ *
+ * Note that the people from hpoj.sourceforge.net need to be able to
+ * bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
+ *
+ * Failing 7/1/2, we look for 7/1/3, even though it's probably not
+ * stream-compatible, because this matches the behaviour of the old code.
+ *
+ * If nothing else, we bind to 7/1/1 - the unidirectional interface.
+ */
+static int usblp_select_alts(struct usblp *usblp)
+{
+ struct usb_interface *if_alt;
+ struct usb_interface_descriptor *ifd;
+ struct usb_endpoint_descriptor *epd, *epwrite, *epread;
+ int p, i, e;
+
+ if_alt = &usblp->dev->actconfig->interface[usblp->ifnum];
+
+ for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
+ usblp->protocol[p].alt_setting = -1;
+
+ /* Find out what we have. */
+ for (i = 0; i < if_alt->num_altsetting; i++) {
+ ifd = &if_alt->altsetting[i];
+
+ if (ifd->bInterfaceClass != 7 || ifd->bInterfaceSubClass != 1)
+ continue;
+
+ if (ifd->bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
+ ifd->bInterfaceProtocol > USBLP_LAST_PROTOCOL)
+ continue;
+
+ /* Look for bulk OUT and IN endpoints. */
+ epwrite = epread = 0;
+ for (e = 0; e < ifd->bNumEndpoints; e++) {
+ epd = &ifd->endpoint[e];
+
+ if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
+ USB_ENDPOINT_XFER_BULK)
+ continue;
+
+ if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
+ if (!epwrite) epwrite=epd;
+
+ } else {
+ if (!epread) epread=epd;
+ }
+ }
+
+ /* Ignore buggy hardware without the right endpoints. */
+ if (!epwrite || (ifd->bInterfaceProtocol > 1 && !epread))
+ continue;
+
+ /* Turn off reads for 7/1/1 (unidirectional) interfaces
+ * and buggy bidirectional printers. */
+ if (ifd->bInterfaceProtocol == 1) {
+ epread = NULL;
+ } else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
+ info("Disabling reads from problem bidirectional "
+ "printer on usblp%d", usblp->minor);
+ epread = NULL;
+ }
+
+ usblp->protocol[ifd->bInterfaceProtocol].alt_setting = i;
+ usblp->protocol[ifd->bInterfaceProtocol].epwrite = epwrite;
+ usblp->protocol[ifd->bInterfaceProtocol].epread = epread;
+ }
+
+ /* If our requested protocol is supported, then use it. */
+ if (proto_bias >= USBLP_FIRST_PROTOCOL &&
+ proto_bias <= USBLP_LAST_PROTOCOL &&
+ usblp->protocol[proto_bias].alt_setting != -1)
+ return proto_bias;
+
+ /* Ordering is important here. */
+ if (usblp->protocol[2].alt_setting != -1) return 2;
+ if (usblp->protocol[1].alt_setting != -1) return 1;
+ if (usblp->protocol[3].alt_setting != -1) return 3;
+
+ /* If nothing is available, then don't bind to this device. */
+ return -1;
+}
+
+static int usblp_set_protocol(struct usblp *usblp, int protocol)
+{
+ int r, alts;
+
+ if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
+ return -EINVAL;
+
+ alts = usblp->protocol[protocol].alt_setting;
+ if (alts < 0) return -EINVAL;
+ r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
+ if (r < 0) {
+ err("can't set desired altsetting %d on interface %d",
+ alts, usblp->ifnum);
+ return r;
+ }
+
+ FILL_BULK_URB(usblp->writeurb, usblp->dev,
+ usb_sndbulkpipe(usblp->dev,
+ usblp->protocol[protocol].epwrite->bEndpointAddress),
+ usblp->buf, 0,
+ usblp_bulk_write, usblp);
+
+ usblp->bidir = (usblp->protocol[protocol].epread != 0);
+ if (usblp->bidir)
+ FILL_BULK_URB(usblp->readurb, usblp->dev,
+ usb_rcvbulkpipe(usblp->dev,
+ usblp->protocol[protocol].epread->bEndpointAddress),
+ usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
+ usblp_bulk_read, usblp);
+
+ usblp->current_protocol = protocol;
+ dbg("usblp%d set protocol %d", usblp->minor, protocol);
+ return 0;
+}
+
+/* Retrieves and caches device ID string.
+ * Returns length, including length bytes but not null terminator.
+ * On error, returns a negative errno value. */
+static int usblp_cache_device_id_string(struct usblp *usblp)
+{
+ int err, length;
+
+ err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
+ if (err < 0) {
+ dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
+ usblp->minor, err);
+ usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
+ return -EIO;
+ }
+
+ /* First two bytes are length in big-endian.
+ * They count themselves, and we copy them into
+ * the user's buffer. */
+ length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
+ if (length < 2)
+ length = 2;
+ else if (length >= DEVICE_ID_SIZE)
+ length = DEVICE_ID_SIZE - 1;
+ usblp->device_id_string[length] = '\0';
+
+ dbg("usblp%d Device ID string [len=%d]=\"%s\"",
+ usblp->minor, length, &usblp->device_id_string[2]);
+
+ return length;
}
static void usblp_disconnect(struct usb_device *dev, void *ptr)
@@ -757,9 +1055,7 @@ static void usblp_disconnect(struct usb_device *dev, void *ptr)
lock_kernel();
usblp->dev = NULL;
- usb_unlink_urb(usblp->writeurb);
- if (usblp->bidir)
- usb_unlink_urb(usblp->readurb);
+ usblp_unlink_urbs(usblp);
if (!usblp->used)
usblp_cleanup (usblp);
@@ -794,7 +1090,7 @@ static int __init usblp_init(void)
{
if (usb_register(&usblp_driver))
return -1;
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ info(DRIVER_VERSION ": " DRIVER_DESC);
return 0;
}
@@ -808,5 +1104,6 @@ module_exit(usblp_exit);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_PARM(proto_bias, "i");
+MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index f185987c6541..812726b110fa 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -262,7 +262,7 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u
port);
/* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
/* Throw away data. No better idea what to do with it. */
@@ -331,7 +331,7 @@ static void cyberjack_read_int_callback( struct urb *urb )
if( !old_rdtodo ) {
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if( result )
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
@@ -387,7 +387,7 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
/* Continue to read if we have still urbs to do. */
if( priv->rdtodo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
@@ -440,7 +440,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
port);
/* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
/* Throw away data. No better idea what to do with it. */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 621af4d63ebc..a03c9b4a9a1d 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -676,7 +676,7 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, co
oob_port->write_urb->transfer_buffer_length = len;
oob_port->write_urb->dev = port->serial->dev;
- if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) {
oob_priv->dp_write_urb_in_use = 1;
count -= len;
buf += len;
@@ -764,7 +764,7 @@ count );
}
port->write_urb->dev = port->serial->dev;
- if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
count -= len;
@@ -841,7 +841,7 @@ port_priv->dp_port_num, modem_signals );
oob_port->write_urb->transfer_buffer_length = 8;
oob_port->write_urb->dev = port->serial->dev;
- if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) {
oob_priv->dp_write_urb_in_use = 1;
port_priv->dp_modem_signals =
(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
@@ -962,7 +962,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
/* restart read chain */
if( priv->dp_throttle_restart ) {
port->read_urb->dev = port->serial->dev;
- ret = usb_submit_urb( port->read_urb, GFP_KERNEL );
+ ret = usb_submit_urb( port->read_urb, GFP_ATOMIC );
}
/* turn throttle off */
@@ -1323,7 +1323,7 @@ priv->dp_port_num, count, from_user, in_interrupt() );
/* copy in new data */
memcpy( data, from_user ? user_buf : buf, new_len );
- if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1;
ret = new_len;
priv->dp_out_buf_len = 0;
@@ -1399,7 +1399,7 @@ dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf,
priv->dp_out_buf_len );
- if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
+ if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
}
@@ -1837,7 +1837,7 @@ dbg( "digi_read_bulk_callback: TOP" );
/* continue read */
urb->dev = port->serial->dev;
- if( (ret=usb_submit_urb(urb, GFP_KERNEL)) != 0 ) {
+ if( (ret=usb_submit_urb(urb, GFP_ATOMIC)) != 0 ) {
err( __FUNCTION__ ": failed resubmitting urb, ret=%d, port=%d",
ret, priv->dp_port_num );
}
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 3a636d7a4740..fa390d5c32cc 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -256,7 +256,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
}
if (urb->transfer_buffer == NULL) {
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
err(__FUNCTION__" no more kernel memory...");
goto exit;
@@ -288,7 +288,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
- status = usb_submit_urb(urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
bytes_sent = status;
@@ -441,7 +441,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_flags |= USB_QUEUE_BULK;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
@@ -466,7 +466,7 @@ static void empeg_unthrottle (struct usb_serial_port *port)
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 911d3ac53f94..fc07f8f67835 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -469,7 +469,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
port->write_urb->transfer_buffer, count,
ftdi_sio_write_bulk_callback, port);
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
return 0;
@@ -631,7 +631,7 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ftdi_sio_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 60194ede19d8..393fbafd21e2 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -790,7 +790,7 @@ static void edge_interrupt_callback (struct urb *urb)
/* we have pending bytes on the bulk in pipe, send a request */
edge_serial->read_urb->dev = edge_serial->serial->dev;
- result = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (result) {
dbg(__FUNCTION__" - usb_submit_urb(read bulk) failed with result = %d", result);
}
@@ -867,7 +867,7 @@ static void edge_bulk_in_callback (struct urb *urb)
/* there is, so resubmit our urb */
edge_serial->read_urb->dev = edge_serial->serial->dev;
- status = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL);
+ status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (status) {
err(__FUNCTION__" - usb_submit_urb(read bulk) failed, status = %d", status);
}
@@ -1435,7 +1435,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
/* build the data header for the buffer and port that we are about to send out */
count = fifo->count;
- buffer = kmalloc (count+2, GFP_KERNEL);
+ buffer = kmalloc (count+2, GFP_ATOMIC);
if (buffer == NULL) {
err(__FUNCTION__" - no more kernel memory...");
edge_port->write_in_progress = FALSE;
@@ -1474,7 +1474,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
urb->transfer_flags |= USB_QUEUE_BULK;
urb->dev = edge_serial->serial->dev;
- status = usb_submit_urb(urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
@@ -2431,7 +2431,7 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
dbg(__FUNCTION__" - %d, %d", command, param);
- buffer = kmalloc (10, GFP_KERNEL);
+ buffer = kmalloc (10, GFP_ATOMIC);
if (!buffer) {
err(__FUNCTION__" - kmalloc(%d) failed.\n", 10);
return -ENOMEM;
@@ -2467,7 +2467,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer);
/* Allocate our next urb */
- urb = usb_alloc_urb (0, GFP_KERNEL);
+ urb = usb_alloc_urb (0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
@@ -2482,7 +2482,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
urb->transfer_flags |= USB_QUEUE_BULK;
edge_port->commandPending = TRUE;
- status = usb_submit_urb(urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
@@ -2532,7 +2532,7 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
}
// Alloc memory for the string of commands.
- cmdBuffer = kmalloc (0x100, GFP_KERNEL);
+ cmdBuffer = kmalloc (0x100, GFP_ATOMIC);
if (!cmdBuffer) {
err(__FUNCTION__" - kmalloc(%d) failed.\n", 0x100);
return -ENOMEM;
@@ -2618,7 +2618,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
dbg (__FUNCTION__" - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", regValue);
// Alloc memory for the string of commands.
- cmdBuffer = kmalloc (0x10, GFP_KERNEL);
+ cmdBuffer = kmalloc (0x10, GFP_ATOMIC);
if (cmdBuffer == NULL ) {
return -ENOMEM;
}
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index c839920d236a..c3e9c8791fa9 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -297,7 +297,7 @@ static void ipaq_read_bulk_callback(struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ipaq_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
@@ -412,7 +412,7 @@ static int ipaq_write_flush(struct usb_serial_port *port)
usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
port);
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
}
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index f44ae514529a..5a8f68918b67 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -405,7 +405,7 @@ static int ir_write (struct usb_serial_port *port, int from_user, const unsigned
= USB_QUEUE_BULK
| USB_ZERO_PACKET;
- result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
else
@@ -515,7 +515,7 @@ static void ir_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_flags = USB_QUEUE_BULK;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err("%s - failed resubmitting read urb, error %d",
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index d8d8a2e83bb2..2879204149e1 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -378,7 +378,7 @@ static int keyspan_write(struct usb_serial_port *port, int from_user,
this_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
this_urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(this_urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
dbg("usb_submit_urb(write bulk) failed (%d)\n", err);
}
p_priv->tx_start_time[flip] = jiffies;
@@ -436,7 +436,7 @@ static void usa26_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
return;
@@ -535,7 +535,7 @@ static void usa26_instat_callback(struct urb *urb)
exit:
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
@@ -586,7 +586,7 @@ static void usa28_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n",
err);
}
@@ -671,7 +671,7 @@ static void usa28_instat_callback(struct urb *urb)
exit:
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
@@ -764,7 +764,7 @@ exit:
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
@@ -819,7 +819,7 @@ static void usa49_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
- if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index ae37c1ff9b86..54b09b26e43c 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -292,7 +292,7 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
/* just restart the receive interrupt URB */
dbg("keyspan_pda_rx_unthrottle port %d", port->number);
port->interrupt_in_urb->dev = port->serial->dev;
- if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
+ if (usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC))
dbg(" usb_submit_urb(read urb) failed");
return;
}
@@ -584,7 +584,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user,
priv->tx_room -= count;
port->write_urb->dev = port->serial->dev;
- rc = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ rc = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (rc) {
dbg(" usb_submit_urb(write bulk) failed");
goto exit;
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 3aa9c40e2c61..5b0e1b944dcb 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -519,7 +519,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
}
if (urb->transfer_buffer == NULL) {
- urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
err(__FUNCTION__ " - no more kernel memory...");
goto exit;
@@ -555,7 +555,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
/* send the data out the bulk port */
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__
" - failed submitting write urb, error %d", result);
@@ -721,7 +721,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer_length,
klsi_105_read_bulk_callback,
port);
- rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (rc)
err(__FUNCTION__
" - failed resubmitting read urb, error %d", rc);
@@ -1019,7 +1019,7 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number);
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d",
result);
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 1151d0d2170a..125c4a647ab3 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -470,7 +470,7 @@ static int mct_u232_write (struct usb_serial_port *port, int from_user,
port);
/* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__
" - failed submitting write urb, error %d", result);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 2eb34c553790..457984644e9b 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -265,7 +265,7 @@ static void omninet_read_bulk_callback (struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
urb->transfer_buffer, urb->transfer_buffer_length,
omninet_read_bulk_callback, port);
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
@@ -316,7 +316,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns
wport->write_urb->transfer_buffer_length = 64;
wport->write_urb->dev = serial->dev;
- result = usb_submit_urb(wport->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 57dedd00441c..23adb9024f46 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -195,7 +195,7 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const uns
port->write_urb->transfer_buffer_length = count;
port->write_urb->dev = port->serial->dev;
- result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else
@@ -643,7 +643,7 @@ static void pl2303_read_bulk_callback (struct urb *urb)
dbg (__FUNCTION__ " - caught -EPROTO, resubmitting the urb");
urb->status = 0;
urb->dev = serial->dev;
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
@@ -668,7 +668,7 @@ static void pl2303_read_bulk_callback (struct urb *urb)
/* Schedule the next read _if_ we are still open */
if (port->open_count) {
urb->dev = serial->dev;
- result = usb_submit_urb(urb, GFP_KERNEL);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
@@ -697,7 +697,7 @@ static void pl2303_write_bulk_callback (struct urb *urb)
dbg (__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
port->write_urb->transfer_buffer_length = 1;
port->write_urb->dev = port->serial->dev;
- result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting write urb, error %d", result);
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
index 4746b8107f45..6271ade640d6 100644
--- a/drivers/usb/serial/usbserial.c
+++ b/drivers/usb/serial/usbserial.c
@@ -899,7 +899,7 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns
generic_write_bulk_callback), port);
/* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else
@@ -989,7 +989,7 @@ static void generic_read_bulk_callback (struct urb *urb)
((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback :
generic_read_bulk_callback), port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 2ac4489b92d8..29415d2e2fb1 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -344,13 +344,13 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
dbg(__FUNCTION__ " - port %d", port->number);
- buffer = kmalloc (count, GFP_KERNEL);
+ buffer = kmalloc (count, GFP_ATOMIC);
if (!buffer) {
err ("out of memory");
return -ENOMEM;
}
- urb = usb_alloc_urb(0, GFP_KERNEL);
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
err ("no more free urbs");
kfree (buffer);
@@ -377,7 +377,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
- status = usb_submit_urb(urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
count = status;
@@ -491,7 +491,7 @@ static void visor_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
visor_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
@@ -512,7 +512,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number);
port->read_urb->dev = port->serial->dev;
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
}
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 4485b3d26936..3a1dcf663a3a 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -240,7 +240,7 @@ static void command_port_read_callback (struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
command_port_read_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
dbg(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 76eda773d051..9d924215e12c 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -6,7 +6,226 @@
* table of configured filesystems
*/
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/kmod.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+/*
+ * Handling of filesystem drivers list.
+ * Rules:
+ * Inclusion to/removals from/scanning of list are protected by spinlock.
+ * During the unload module must call unregister_filesystem().
+ * We can access the fields of list element if:
+ * 1) spinlock is held or
+ * 2) we hold the reference to the module.
+ * The latter can be guaranteed by call of try_inc_mod_count(); if it
+ * returned 0 we must skip the element, otherwise we got the reference.
+ * Once the reference is obtained we can drop the spinlock.
+ */
+
+static struct file_system_type *file_systems;
+static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
+
+/* WARNING: This can be used only if we _already_ own a reference */
+void get_filesystem(struct file_system_type *fs)
+{
+ if (fs->owner)
+ __MOD_INC_USE_COUNT(fs->owner);
+}
+
+void put_filesystem(struct file_system_type *fs)
+{
+ if (fs->owner)
+ __MOD_DEC_USE_COUNT(fs->owner);
+}
+
+static struct file_system_type **find_filesystem(const char *name)
+{
+ struct file_system_type **p;
+ for (p=&file_systems; *p; p=&(*p)->next)
+ if (strcmp((*p)->name,name) == 0)
+ break;
+ return p;
+}
+
+/**
+ * register_filesystem - register a new filesystem
+ * @fs: the file system structure
+ *
+ * Adds the file system passed to the list of file systems the kernel
+ * is aware of for mount and other syscalls. Returns 0 on success,
+ * or a negative errno code on an error.
+ *
+ * The &struct file_system_type that is passed is linked into the kernel
+ * structures and must not be freed until the file system has been
+ * unregistered.
+ */
+
+int register_filesystem(struct file_system_type * fs)
+{
+ int res = 0;
+ struct file_system_type ** p;
+
+ if (!fs)
+ return -EINVAL;
+ if (fs->next)
+ return -EBUSY;
+ INIT_LIST_HEAD(&fs->fs_supers);
+ write_lock(&file_systems_lock);
+ p = find_filesystem(fs->name);
+ if (*p)
+ res = -EBUSY;
+ else
+ *p = fs;
+ write_unlock(&file_systems_lock);
+ return res;
+}
+
+/**
+ * unregister_filesystem - unregister a file system
+ * @fs: filesystem to unregister
+ *
+ * Remove a file system that was previously successfully registered
+ * with the kernel. An error is returned if the file system is not found.
+ * Zero is returned on a success.
+ *
+ * Once this function has returned the &struct file_system_type structure
+ * may be freed or reused.
+ */
+
+int unregister_filesystem(struct file_system_type * fs)
+{
+ struct file_system_type ** tmp;
+
+ write_lock(&file_systems_lock);
+ tmp = &file_systems;
+ while (*tmp) {
+ if (fs == *tmp) {
+ *tmp = fs->next;
+ fs->next = NULL;
+ write_unlock(&file_systems_lock);
+ return 0;
+ }
+ tmp = &(*tmp)->next;
+ }
+ write_unlock(&file_systems_lock);
+ return -EINVAL;
+}
+
+static int fs_index(const char * __name)
+{
+ struct file_system_type * tmp;
+ char * name;
+ int err, index;
+
+ name = getname(__name);
+ err = PTR_ERR(name);
+ if (IS_ERR(name))
+ return err;
+
+ err = -EINVAL;
+ read_lock(&file_systems_lock);
+ for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
+ if (strcmp(tmp->name,name) == 0) {
+ err = index;
+ break;
+ }
+ }
+ read_unlock(&file_systems_lock);
+ putname(name);
+ return err;
+}
+
+static int fs_name(unsigned int index, char * buf)
+{
+ struct file_system_type * tmp;
+ int len, res;
+
+ read_lock(&file_systems_lock);
+ for (tmp = file_systems; tmp; tmp = tmp->next, index--)
+ if (index <= 0 && try_inc_mod_count(tmp->owner))
+ break;
+ read_unlock(&file_systems_lock);
+ if (!tmp)
+ return -EINVAL;
+
+ /* OK, we got the reference, so we can safely block */
+ len = strlen(tmp->name) + 1;
+ res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
+ put_filesystem(tmp);
+ return res;
+}
+
+static int fs_maxindex(void)
+{
+ struct file_system_type * tmp;
+ int index;
+
+ read_lock(&file_systems_lock);
+ for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
+ ;
+ read_unlock(&file_systems_lock);
+ return index;
+}
+
/*
- * Code will move here from fs/super.c and yes, it will be fs type handling
- * stuff.
+ * Whee.. Weird sysv syscall.
*/
+asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
+{
+ int retval = -EINVAL;
+
+ switch (option) {
+ case 1:
+ retval = fs_index((const char *) arg1);
+ break;
+
+ case 2:
+ retval = fs_name(arg1, (char *) arg2);
+ break;
+
+ case 3:
+ retval = fs_maxindex();
+ break;
+ }
+ return retval;
+}
+
+int get_filesystem_list(char * buf)
+{
+ int len = 0;
+ struct file_system_type * tmp;
+
+ read_lock(&file_systems_lock);
+ tmp = file_systems;
+ while (tmp && len < PAGE_SIZE - 80) {
+ len += sprintf(buf+len, "%s\t%s\n",
+ (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
+ tmp->name);
+ tmp = tmp->next;
+ }
+ read_unlock(&file_systems_lock);
+ return len;
+}
+
+struct file_system_type *get_fs_type(const char *name)
+{
+ struct file_system_type *fs;
+
+ read_lock(&file_systems_lock);
+ fs = *(find_filesystem(name));
+ if (fs && !try_inc_mod_count(fs->owner))
+ fs = NULL;
+ read_unlock(&file_systems_lock);
+ if (!fs && (request_module(name) == 0)) {
+ read_lock(&file_systems_lock);
+ fs = *(find_filesystem(name));
+ if (fs && !try_inc_mod_count(fs->owner))
+ fs = NULL;
+ read_unlock(&file_systems_lock);
+ }
+ return fs;
+}
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 583ade0421c0..bef27095249e 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -110,14 +110,13 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
struct buffer_head *bh = NULL;
int len;
int map;
- int high_sierra;
int first_de = 1;
char *p = NULL; /* Quiet GCC */
struct iso_directory_record *de;
+ struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
offset = filp->f_pos & (bufsize - 1);
block = filp->f_pos >> bufbits;
- high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
while (filp->f_pos < inode->i_size) {
int de_len;
@@ -166,7 +165,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
de = tmpde;
}
- if (de->flags[-high_sierra] & 0x80) {
+ if (de->flags[-sbi->s_high_sierra] & 0x80) {
first_de = 0;
filp->f_pos += de_len;
continue;
@@ -194,16 +193,16 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
/* Handle everything else. Do name translation if there
is no Rock Ridge NM field. */
- if (inode->i_sb->u.isofs_sb.s_unhide == 'n') {
+ if (sbi->s_unhide == 'n') {
/* Do not report hidden or associated files */
- if (de->flags[-high_sierra] & 5) {
+ if (de->flags[-sbi->s_high_sierra] & 5) {
filp->f_pos += de_len;
continue;
}
}
map = 1;
- if (inode->i_sb->u.isofs_sb.s_rock) {
+ if (sbi->s_rock) {
len = get_rock_ridge_filename(de, tmpname, inode);
if (len != 0) { /* may be -1 */
p = tmpname;
@@ -212,16 +211,16 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
}
if (map) {
#ifdef CONFIG_JOLIET
- if (inode->i_sb->u.isofs_sb.s_joliet_level) {
+ if (sbi->s_joliet_level) {
len = get_joliet_filename(de, tmpname, inode);
p = tmpname;
} else
#endif
- if (inode->i_sb->u.isofs_sb.s_mapping == 'a') {
+ if (sbi->s_mapping == 'a') {
len = get_acorn_filename(de, tmpname, inode);
p = tmpname;
} else
- if (inode->i_sb->u.isofs_sb.s_mapping == 'n') {
+ if (sbi->s_mapping == 'n') {
len = isofs_name_translate(de, tmpname, inode);
p = tmpname;
} else {
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index d1bec1eae0a0..31174ae2bede 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -60,10 +60,11 @@ static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qst
static void isofs_put_super(struct super_block *sb)
{
+ struct isofs_sb_info *sbi = ISOFS_SB(sb);
#ifdef CONFIG_JOLIET
- if (sb->u.isofs_sb.s_nls_iocharset) {
- unload_nls(sb->u.isofs_sb.s_nls_iocharset);
- sb->u.isofs_sb.s_nls_iocharset = NULL;
+ if (sbi->s_nls_iocharset) {
+ unload_nls(sbi->s_nls_iocharset);
+ sbi->s_nls_iocharset = NULL;
}
#endif
@@ -72,6 +73,8 @@ static void isofs_put_super(struct super_block *sb)
check_malloc, check_bread);
#endif
+ kfree(sbi);
+ sb->u.generic_sbp = NULL;
return;
}
@@ -518,7 +521,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
struct iso_supplementary_descriptor *sec = NULL;
struct iso_directory_record * rootp;
int joliet_level = 0;
- int high_sierra;
int iso_blknum, block;
int orig_zonesize;
int table;
@@ -526,9 +528,16 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
unsigned long first_data_zone;
struct inode * inode;
struct iso9660_options opt;
+ struct isofs_sb_info * sbi;
+
+ sbi = kmalloc(sizeof(struct isofs_sb_info), GFP_KERNEL);
+ if (!sbi)
+ return -ENOMEM;
+ s->u.generic_sbp = sbi;
+ memset(sbi, 0, sizeof(struct isofs_sb_info));
if (!parse_options((char *) data, &opt))
- goto out_unlock;
+ goto out_freesbi;
#if 0
printk("map = %c\n", opt.map);
@@ -554,7 +563,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
*/
opt.blocksize = sb_min_blocksize(s, opt.blocksize);
- s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
+ sbi->s_high_sierra = 0; /* default is iso9660 */
vol_desc_start = (opt.sbsector != -1) ?
opt.sbsector : isofs_get_last_session(s,opt.session);
@@ -614,8 +623,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
goto out_freebh;
- s->u.isofs_sb.s_high_sierra = 1;
- high_sierra = 1;
+ sbi->s_high_sierra = 1;
opt.rock = 'n';
h_pri = (struct hs_primary_descriptor *)vdp;
goto root_found;
@@ -646,29 +654,29 @@ root_found:
pri = (struct iso_primary_descriptor *) sec;
}
- if(high_sierra){
+ if(sbi->s_high_sierra){
rootp = (struct iso_directory_record *) h_pri->root_directory_record;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
if (isonum_723 (h_pri->volume_set_size) != 1)
goto out_no_support;
#endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */
- s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
- s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
- s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
+ sbi->s_nzones = isonum_733 (h_pri->volume_space_size);
+ sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size);
+ sbi->s_max_size = isonum_733(h_pri->volume_space_size);
} else {
rootp = (struct iso_directory_record *) pri->root_directory_record;
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
if (isonum_723 (pri->volume_set_size) != 1)
goto out_no_support;
#endif /* IGNORE_WRONG_MULTI_VOLUME_SPECS */
- s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
- s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
- s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
+ sbi->s_nzones = isonum_733 (pri->volume_space_size);
+ sbi->s_log_zone_size = isonum_723 (pri->logical_block_size);
+ sbi->s_max_size = isonum_733(pri->volume_space_size);
}
- s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
+ sbi->s_ninodes = 0; /* No way to figure this out easily */
- orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
+ orig_zonesize = sbi->s_log_zone_size;
/*
* If the zone size is smaller than the hardware sector size,
* this is a fatal error. This would occur if the disc drive
@@ -680,10 +688,10 @@ root_found:
goto out_bad_size;
/* RDE: convert log zone size to bit shift */
- switch (s -> u.isofs_sb.s_log_zone_size)
- { case 512: s -> u.isofs_sb.s_log_zone_size = 9; break;
- case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
- case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break;
+ switch (sbi->s_log_zone_size)
+ { case 512: sbi->s_log_zone_size = 9; break;
+ case 1024: sbi->s_log_zone_size = 10; break;
+ case 2048: sbi->s_log_zone_size = 11; break;
default:
goto out_bad_zone_size;
@@ -705,16 +713,16 @@ root_found:
first_data_zone = ((isonum_733 (rootp->extent) +
isonum_711 (rootp->ext_attr_length))
- << s -> u.isofs_sb.s_log_zone_size);
- s->u.isofs_sb.s_firstdatazone = first_data_zone;
+ << sbi->s_log_zone_size);
+ sbi->s_firstdatazone = first_data_zone;
#ifndef BEQUIET
printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n",
- s->u.isofs_sb.s_max_size,
- 1UL << s->u.isofs_sb.s_log_zone_size);
+ sbi->s_max_size,
+ 1UL << sbi->s_log_zone_size);
printk(KERN_DEBUG "First datazone:%ld Root inode number:%ld\n",
- s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
- s->u.isofs_sb.s_firstdatazone);
- if(high_sierra)
+ sbi->s_firstdatazone >> sbi->s_log_zone_size,
+ sbi->s_firstdatazone);
+ if(sbi->s_high_sierra)
printk(KERN_DEBUG "Disc in High Sierra format.\n");
#endif
@@ -732,7 +740,7 @@ root_found:
pri->root_directory_record;
first_data_zone = ((isonum_733 (rootp->extent) +
isonum_711 (rootp->ext_attr_length))
- << s -> u.isofs_sb.s_log_zone_size);
+ << sbi->s_log_zone_size);
}
/*
@@ -761,43 +769,43 @@ root_found:
*/
sb_set_blocksize(s, orig_zonesize);
- s->u.isofs_sb.s_nls_iocharset = NULL;
+ sbi->s_nls_iocharset = NULL;
#ifdef CONFIG_JOLIET
if (joliet_level && opt.utf8 == 0) {
char * p = opt.iocharset ? opt.iocharset : "iso8859-1";
- s->u.isofs_sb.s_nls_iocharset = load_nls(p);
- if (! s->u.isofs_sb.s_nls_iocharset) {
+ sbi->s_nls_iocharset = load_nls(p);
+ if (! sbi->s_nls_iocharset) {
/* Fail only if explicit charset specified */
if (opt.iocharset)
- goto out_unlock;
- s->u.isofs_sb.s_nls_iocharset = load_nls_default();
+ goto out_freesbi;
+ sbi->s_nls_iocharset = load_nls_default();
}
}
#endif
s->s_op = &isofs_sops;
- s->u.isofs_sb.s_mapping = opt.map;
- s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 2 : 0);
- s->u.isofs_sb.s_rock_offset = -1; /* initial offset, will guess until SP is found*/
- s->u.isofs_sb.s_cruft = opt.cruft;
- s->u.isofs_sb.s_unhide = opt.unhide;
- s->u.isofs_sb.s_uid = opt.uid;
- s->u.isofs_sb.s_gid = opt.gid;
- s->u.isofs_sb.s_utf8 = opt.utf8;
- s->u.isofs_sb.s_nocompress = opt.nocompress;
+ sbi->s_mapping = opt.map;
+ sbi->s_rock = (opt.rock == 'y' ? 2 : 0);
+ sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
+ sbi->s_cruft = opt.cruft;
+ sbi->s_unhide = opt.unhide;
+ sbi->s_uid = opt.uid;
+ sbi->s_gid = opt.gid;
+ sbi->s_utf8 = opt.utf8;
+ sbi->s_nocompress = opt.nocompress;
/*
* It would be incredibly stupid to allow people to mark every file
* on the disk as suid, so we merely allow them to set the default
* permissions.
*/
- s->u.isofs_sb.s_mode = opt.mode & 0777;
+ sbi->s_mode = opt.mode & 0777;
/*
* Read the root inode, which _may_ result in changing
* the s_rock flag. Once we have the final s_rock value,
* we then decide whether to use the Joliet descriptor.
*/
- inode = iget(s, s->u.isofs_sb.s_firstdatazone);
+ inode = iget(s, sbi->s_firstdatazone);
/*
* If this disk has both Rock Ridge and Joliet on it, then we
@@ -807,16 +815,16 @@ root_found:
* CD with Unicode names. Until someone sees such a beast, it
* will not be supported.
*/
- if (s->u.isofs_sb.s_rock == 1) {
+ if (sbi->s_rock == 1) {
joliet_level = 0;
} else if (joliet_level) {
- s->u.isofs_sb.s_rock = 0;
- if (s->u.isofs_sb.s_firstdatazone != first_data_zone) {
- s->u.isofs_sb.s_firstdatazone = first_data_zone;
+ sbi->s_rock = 0;
+ if (sbi->s_firstdatazone != first_data_zone) {
+ sbi->s_firstdatazone = first_data_zone;
printk(KERN_DEBUG
"ISOFS: changing to secondary root\n");
iput(inode);
- inode = iget(s, s->u.isofs_sb.s_firstdatazone);
+ inode = iget(s, sbi->s_firstdatazone);
}
}
@@ -825,7 +833,7 @@ root_found:
if (joliet_level) opt.check = 'r';
else opt.check = 's';
}
- s->u.isofs_sb.s_joliet_level = joliet_level;
+ sbi->s_joliet_level = joliet_level;
/* check the root inode */
if (!inode)
@@ -855,18 +863,18 @@ out_no_root:
out_iput:
iput(inode);
#ifdef CONFIG_JOLIET
- if (s->u.isofs_sb.s_nls_iocharset)
- unload_nls(s->u.isofs_sb.s_nls_iocharset);
+ if (sbi->s_nls_iocharset)
+ unload_nls(sbi->s_nls_iocharset);
#endif
- goto out_unlock;
+ goto out_freesbi;
out_no_read:
printk(KERN_WARNING "isofs_fill_super: "
"bread failed, dev=%s, iso_blknum=%d, block=%d\n",
s->s_id, iso_blknum, block);
- goto out_unlock;
+ goto out_freesbi;
out_bad_zone_size:
printk(KERN_WARNING "Bad logical zone size %ld\n",
- s->u.isofs_sb.s_log_zone_size);
+ sbi->s_log_zone_size);
goto out_freebh;
out_bad_size:
printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n",
@@ -883,7 +891,9 @@ out_unknown_format:
out_freebh:
brelse(bh);
-out_unlock:
+out_freesbi:
+ kfree(sbi);
+ s->u.generic_sbp = NULL;
return -EINVAL;
}
@@ -891,11 +901,11 @@ static int isofs_statfs (struct super_block *sb, struct statfs *buf)
{
buf->f_type = ISOFS_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
- buf->f_blocks = (sb->u.isofs_sb.s_nzones
- << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
+ buf->f_blocks = (ISOFS_SB(sb)->s_nzones
+ << (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits));
buf->f_bfree = 0;
buf->f_bavail = 0;
- buf->f_files = sb->u.isofs_sb.s_ninodes;
+ buf->f_files = ISOFS_SB(sb)->s_ninodes;
buf->f_ffree = 0;
buf->f_namelen = NAME_MAX;
return 0;
@@ -1058,7 +1068,7 @@ static int isofs_read_level3_size(struct inode * inode)
{
unsigned long f_pos = inode->i_ino;
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
- int high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
+ int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
struct buffer_head * bh = NULL;
unsigned long block, offset;
int i = 0;
@@ -1157,9 +1167,10 @@ out_toomany:
static void isofs_read_inode(struct inode * inode)
{
struct super_block *sb = inode->i_sb;
+ struct isofs_sb_info *sbi = ISOFS_SB(sb);
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
- int high_sierra = sb->u.isofs_sb.s_high_sierra;
+ int high_sierra = sbi->s_high_sierra;
struct buffer_head * bh = NULL;
struct iso_directory_record * de;
struct iso_directory_record * tmpde = NULL;
@@ -1205,7 +1216,7 @@ static void isofs_read_inode(struct inode * inode)
do it the hard way. */
} else {
/* Everybody gets to read the file. */
- inode->i_mode = inode->i_sb->u.isofs_sb.s_mode;
+ inode->i_mode = sbi->s_mode;
inode->i_nlink = 1;
inode->i_mode |= S_IFREG;
/* If there are no periods in the name,
@@ -1217,8 +1228,8 @@ static void isofs_read_inode(struct inode * inode)
if(i == de->name_len[0] || de->name[i] == ';')
inode->i_mode |= S_IXUGO; /* execute permission */
}
- inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
- inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
+ inode->i_uid = sbi->s_uid;
+ inode->i_gid = sbi->s_gid;
inode->i_blocks = inode->i_blksize = 0;
ei->i_format_parm[0] = 0;
@@ -1241,10 +1252,10 @@ static void isofs_read_inode(struct inode * inode)
* legal. Do not prevent to use DVD's schilling@fokus.gmd.de
*/
if ((inode->i_size < 0 || inode->i_size > 0x7FFFFFFE) &&
- inode->i_sb->u.isofs_sb.s_cruft == 'n') {
+ sbi->s_cruft == 'n') {
printk(KERN_WARNING "Warning: defective CD-ROM. "
"Enabling \"cruft\" mount option.\n");
- inode->i_sb->u.isofs_sb.s_cruft = 'y';
+ sbi->s_cruft = 'y';
}
/*
@@ -1254,7 +1265,7 @@ static void isofs_read_inode(struct inode * inode)
* on the CDROM.
*/
- if (inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
+ if (sbi->s_cruft == 'y' &&
inode->i_size & 0xff000000) {
inode->i_size &= 0x00ffffff;
}
@@ -1298,8 +1309,8 @@ static void isofs_read_inode(struct inode * inode)
if (!high_sierra) {
parse_rock_ridge_inode(de, inode);
/* if we want uid/gid set, override the rock ridge setting */
- test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
- test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid);
+ test_and_set_uid(&inode->i_uid, sbi->s_uid);
+ test_and_set_gid(&inode->i_gid, sbi->s_gid);
}
/* get the volume sequence number */
@@ -1311,17 +1322,17 @@ static void isofs_read_inode(struct inode * inode)
* of which is limiting the file size to 16Mb. Thus we silently allow
* volume numbers of 0 to go through without complaining.
*/
- if (inode->i_sb->u.isofs_sb.s_cruft == 'n' &&
+ if (sbi->s_cruft == 'n' &&
(volume_seq_no != 0) && (volume_seq_no != 1)) {
printk(KERN_WARNING "Warning: defective CD-ROM "
"(volume sequence number %d). "
"Enabling \"cruft\" mount option.\n", volume_seq_no);
- inode->i_sb->u.isofs_sb.s_cruft = 'y';
+ sbi->s_cruft = 'y';
}
/* Install the inode operations vector */
#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS
- if (inode->i_sb->u.isofs_sb.s_cruft != 'y' &&
+ if (sbi->s_cruft != 'y' &&
(volume_seq_no != 0) && (volume_seq_no != 1)) {
printk(KERN_WARNING "Multi-volume CD somehow got mounted.\n");
} else
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c
index 15d2370bda3f..86c50e22fc87 100644
--- a/fs/isofs/joliet.c
+++ b/fs/isofs/joliet.c
@@ -77,8 +77,8 @@ get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, st
struct nls_table *nls;
unsigned char len = 0;
- utf8 = inode->i_sb->u.isofs_sb.s_utf8;
- nls = inode->i_sb->u.isofs_sb.s_nls_iocharset;
+ utf8 = ISOFS_SB(inode->i_sb)->s_utf8;
+ nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset;
if (utf8) {
len = wcsntombs_be(outname, de->name,
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 485bb7023fe2..cbdf44b0164e 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -65,6 +65,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
unsigned int block, f_pos, offset;
struct buffer_head * bh = NULL;
+ struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
if (!ISOFS_I(dir)->i_first_extent)
return 0;
@@ -120,19 +121,19 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
dlen = de->name_len[0];
dpnt = de->name;
- if (dir->i_sb->u.isofs_sb.s_rock &&
+ if (sbi->s_rock &&
((i = get_rock_ridge_filename(de, tmpname, dir)))) {
dlen = i; /* possibly -1 */
dpnt = tmpname;
#ifdef CONFIG_JOLIET
- } else if (dir->i_sb->u.isofs_sb.s_joliet_level) {
+ } else if (sbi->s_joliet_level) {
dlen = get_joliet_filename(de, tmpname, dir);
dpnt = tmpname;
#endif
- } else if (dir->i_sb->u.isofs_sb.s_mapping == 'a') {
+ } else if (sbi->s_mapping == 'a') {
dlen = get_acorn_filename(de, tmpname, dir);
dpnt = tmpname;
- } else if (dir->i_sb->u.isofs_sb.s_mapping == 'n') {
+ } else if (sbi->s_mapping == 'n') {
dlen = isofs_name_translate(de, tmpname, dir);
dpnt = tmpname;
}
@@ -142,8 +143,8 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
*/
match = 0;
if (dlen > 0 &&
- (!(de->flags[-dir->i_sb->u.isofs_sb.s_high_sierra] & 5)
- || dir->i_sb->u.isofs_sb.s_unhide == 'y'))
+ (!(de->flags[-sbi->s_high_sierra] & 5)
+ || sbi->s_unhide == 'y'))
{
match = (isofs_cmp(dentry,dpnt,dlen) == 0);
}
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 5065d2fdccc6..17b2bb5e6908 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -32,7 +32,7 @@
#define CHECK_SP(FAIL) \
if(rr->u.SP.magic[0] != 0xbe) FAIL; \
if(rr->u.SP.magic[1] != 0xef) FAIL; \
- inode->i_sb->u.isofs_sb.s_rock_offset=rr->u.SP.skip;
+ ISOFS_SB(inode->i_sb)->s_rock_offset=rr->u.SP.skip;
/* We define a series of macros because each function must do exactly the
same thing in certain places. We use the macros to ensure that everything
is done correctly */
@@ -51,10 +51,10 @@
if(LEN & 1) LEN++; \
CHR = ((unsigned char *) DE) + LEN; \
LEN = *((unsigned char *) DE) - LEN; \
- if (inode->i_sb->u.isofs_sb.s_rock_offset!=-1) \
+ if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \
{ \
- LEN-=inode->i_sb->u.isofs_sb.s_rock_offset; \
- CHR+=inode->i_sb->u.isofs_sb.s_rock_offset; \
+ LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \
+ CHR+=ISOFS_SB(inode->i_sb)->s_rock_offset; \
if (LEN<0) LEN=0; \
} \
}
@@ -102,7 +102,7 @@ int find_rock_ridge_relocation(struct iso_directory_record * de,
/* Return value if we do not find appropriate record. */
retval = isonum_733 (de->extent);
- if (!inode->i_sb->u.isofs_sb.s_rock) return retval;
+ if (!ISOFS_SB(inode->i_sb)->s_rock) return retval;
SETUP_ROCK_RIDGE(de, chr, len);
repeat:
@@ -162,7 +162,7 @@ int get_rock_ridge_filename(struct iso_directory_record * de,
CONTINUE_DECLS;
int retnamlen = 0, truncate=0;
- if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
+ if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
*retname = 0;
SETUP_ROCK_RIDGE(de, chr, len);
@@ -234,7 +234,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
int symlink_len = 0;
CONTINUE_DECLS;
- if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
+ if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
SETUP_ROCK_RIDGE(de, chr, len);
if (regard_xa)
@@ -272,7 +272,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
CHECK_CE;
break;
case SIG('E','R'):
- inode->i_sb->u.isofs_sb.s_rock = 1;
+ ISOFS_SB(inode->i_sb)->s_rock = 1;
printk(KERN_DEBUG "ISO 9660 Extensions: ");
{ int p;
for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
@@ -368,7 +368,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
reloc = iget(inode->i_sb,
(ISOFS_I(inode)->i_first_extent <<
- inode -> i_sb -> u.isofs_sb.s_log_zone_size));
+ ISOFS_SB(inode->i_sb)->s_log_zone_size));
if (!reloc)
goto out;
inode->i_mode = reloc->i_mode;
@@ -385,7 +385,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
break;
#ifdef CONFIG_ZISOFS
case SIG('Z','F'):
- if ( !inode->i_sb->u.isofs_sb.s_nocompress ) {
+ if ( !ISOFS_SB(inode->i_sb)->s_nocompress ) {
int algo;
algo = isonum_721(rr->u.ZF.algorithm);
if ( algo == SIG('p','z') ) {
@@ -478,8 +478,8 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
int result=parse_rock_ridge_inode_internal(de,inode,0);
/* if rockridge flag was reset and we didn't look for attributes
* behind eventual XA attributes, have a look there */
- if ((inode->i_sb->u.isofs_sb.s_rock_offset==-1)
- &&(inode->i_sb->u.isofs_sb.s_rock==2))
+ if ((ISOFS_SB(inode->i_sb)->s_rock_offset==-1)
+ &&(ISOFS_SB(inode->i_sb)->s_rock==2))
{
result=parse_rock_ridge_inode_internal(de,inode,14);
};
@@ -506,7 +506,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
unsigned char *chr;
struct rock_ridge *rr;
- if (!inode->i_sb->u.isofs_sb.s_rock)
+ if (!ISOFS_SB(inode->i_sb)->s_rock)
panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
block = inode->i_ino >> bufbits;
diff --git a/fs/super.c b/fs/super.c
index 66a6274d1b71..1a2d66737e08 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -25,235 +25,16 @@
#include <linux/locks.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
-#include <linux/major.h>
#include <linux/acct.h>
-
#include <asm/uaccess.h>
-#include <linux/kmod.h>
-#define __NO_VERSION__
-#include <linux/module.h>
+void get_filesystem(struct file_system_type *fs);
+void put_filesystem(struct file_system_type *fs);
+struct file_system_type *get_fs_type(const char *name);
LIST_HEAD(super_blocks);
spinlock_t sb_lock = SPIN_LOCK_UNLOCKED;
-/*
- * Handling of filesystem drivers list.
- * Rules:
- * Inclusion to/removals from/scanning of list are protected by spinlock.
- * During the unload module must call unregister_filesystem().
- * We can access the fields of list element if:
- * 1) spinlock is held or
- * 2) we hold the reference to the module.
- * The latter can be guaranteed by call of try_inc_mod_count(); if it
- * returned 0 we must skip the element, otherwise we got the reference.
- * Once the reference is obtained we can drop the spinlock.
- */
-
-static struct file_system_type *file_systems;
-static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
-
-/* WARNING: This can be used only if we _already_ own a reference */
-static void get_filesystem(struct file_system_type *fs)
-{
- if (fs->owner)
- __MOD_INC_USE_COUNT(fs->owner);
-}
-
-static void put_filesystem(struct file_system_type *fs)
-{
- if (fs->owner)
- __MOD_DEC_USE_COUNT(fs->owner);
-}
-
-static struct file_system_type **find_filesystem(const char *name)
-{
- struct file_system_type **p;
- for (p=&file_systems; *p; p=&(*p)->next)
- if (strcmp((*p)->name,name) == 0)
- break;
- return p;
-}
-
-/**
- * register_filesystem - register a new filesystem
- * @fs: the file system structure
- *
- * Adds the file system passed to the list of file systems the kernel
- * is aware of for mount and other syscalls. Returns 0 on success,
- * or a negative errno code on an error.
- *
- * The &struct file_system_type that is passed is linked into the kernel
- * structures and must not be freed until the file system has been
- * unregistered.
- */
-
-int register_filesystem(struct file_system_type * fs)
-{
- int res = 0;
- struct file_system_type ** p;
-
- if (!fs)
- return -EINVAL;
- if (fs->next)
- return -EBUSY;
- INIT_LIST_HEAD(&fs->fs_supers);
- write_lock(&file_systems_lock);
- p = find_filesystem(fs->name);
- if (*p)
- res = -EBUSY;
- else
- *p = fs;
- write_unlock(&file_systems_lock);
- return res;
-}
-
-/**
- * unregister_filesystem - unregister a file system
- * @fs: filesystem to unregister
- *
- * Remove a file system that was previously successfully registered
- * with the kernel. An error is returned if the file system is not found.
- * Zero is returned on a success.
- *
- * Once this function has returned the &struct file_system_type structure
- * may be freed or reused.
- */
-
-int unregister_filesystem(struct file_system_type * fs)
-{
- struct file_system_type ** tmp;
-
- write_lock(&file_systems_lock);
- tmp = &file_systems;
- while (*tmp) {
- if (fs == *tmp) {
- *tmp = fs->next;
- fs->next = NULL;
- write_unlock(&file_systems_lock);
- return 0;
- }
- tmp = &(*tmp)->next;
- }
- write_unlock(&file_systems_lock);
- return -EINVAL;
-}
-
-static int fs_index(const char * __name)
-{
- struct file_system_type * tmp;
- char * name;
- int err, index;
-
- name = getname(__name);
- err = PTR_ERR(name);
- if (IS_ERR(name))
- return err;
-
- err = -EINVAL;
- read_lock(&file_systems_lock);
- for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
- if (strcmp(tmp->name,name) == 0) {
- err = index;
- break;
- }
- }
- read_unlock(&file_systems_lock);
- putname(name);
- return err;
-}
-
-static int fs_name(unsigned int index, char * buf)
-{
- struct file_system_type * tmp;
- int len, res;
-
- read_lock(&file_systems_lock);
- for (tmp = file_systems; tmp; tmp = tmp->next, index--)
- if (index <= 0 && try_inc_mod_count(tmp->owner))
- break;
- read_unlock(&file_systems_lock);
- if (!tmp)
- return -EINVAL;
-
- /* OK, we got the reference, so we can safely block */
- len = strlen(tmp->name) + 1;
- res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
- put_filesystem(tmp);
- return res;
-}
-
-static int fs_maxindex(void)
-{
- struct file_system_type * tmp;
- int index;
-
- read_lock(&file_systems_lock);
- for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
- ;
- read_unlock(&file_systems_lock);
- return index;
-}
-
-/*
- * Whee.. Weird sysv syscall.
- */
-asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
-{
- int retval = -EINVAL;
-
- switch (option) {
- case 1:
- retval = fs_index((const char *) arg1);
- break;
-
- case 2:
- retval = fs_name(arg1, (char *) arg2);
- break;
-
- case 3:
- retval = fs_maxindex();
- break;
- }
- return retval;
-}
-
-int get_filesystem_list(char * buf)
-{
- int len = 0;
- struct file_system_type * tmp;
-
- read_lock(&file_systems_lock);
- tmp = file_systems;
- while (tmp && len < PAGE_SIZE - 80) {
- len += sprintf(buf+len, "%s\t%s\n",
- (tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
- tmp->name);
- tmp = tmp->next;
- }
- read_unlock(&file_systems_lock);
- return len;
-}
-
-struct file_system_type *get_fs_type(const char *name)
-{
- struct file_system_type *fs;
-
- read_lock(&file_systems_lock);
- fs = *(find_filesystem(name));
- if (fs && !try_inc_mod_count(fs->owner))
- fs = NULL;
- read_unlock(&file_systems_lock);
- if (!fs && (request_module(name) == 0)) {
- read_lock(&file_systems_lock);
- fs = *(find_filesystem(name));
- if (fs && !try_inc_mod_count(fs->owner))
- fs = NULL;
- read_unlock(&file_systems_lock);
- }
- return fs;
-}
-
/**
* alloc_super - create new superblock
*
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 0e668a01a592..2edd4015fb61 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1413,12 +1413,17 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
struct inode *inode=NULL;
struct udf_options uopt;
lb_addr rootdir, fileset;
+ struct udf_sb_info *sbi;
uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
uopt.uid = -1;
uopt.gid = -1;
uopt.umask = 0;
+ sbi = kmalloc(sizeof(struct udf_sb_info), GFP_KERNEL);
+ if (!sbi)
+ return -ENOMEM;
+ sb->u.generic_sbp = sbi;
memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
#if UDFFS_RW != 1
@@ -1607,6 +1612,8 @@ error_out:
udf_close_lvid(sb);
udf_release_data(UDF_SB_LVIDBH(sb));
UDF_SB_FREE(sb);
+ kfree(sbi);
+ sb->u.generic_sbp = NULL;
return -EINVAL;
}
@@ -1697,6 +1704,8 @@ udf_put_super(struct super_block *sb)
udf_close_lvid(sb);
udf_release_data(UDF_SB_LVIDBH(sb));
UDF_SB_FREE(sb);
+ kfree(sb->u.generic_sbp);
+ sb->u.generic_sbp = NULL;
}
/*
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 0dde99415c97..2b264e1cf49a 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -30,6 +30,11 @@
#define UDF_PART_FLAG_REWRITABLE 0x0040
#define UDF_PART_FLAG_OVERWRITABLE 0x0080
+static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
+{
+ return sb->u.generic_sbp;
+}
+
#define UDF_SB_FREE(X)\
{\
if (UDF_SB(X))\
@@ -39,7 +44,6 @@
UDF_SB_PARTMAPS(X) = NULL;\
}\
}
-#define UDF_SB(X) (&((X)->u.udf_sb))
#define UDF_SB_ALLOC_PARTMAPS(X,Y)\
{\
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 836aef50cded..1b4d5a5d1401 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -8,6 +8,8 @@
#include <linux/fs.h>
#include <linux/config.h>
#include <linux/types.h>
+#include <linux/udf_fs_i.h>
+#include <linux/udf_fs_sb.h>
#ifndef LINUX_VERSION_CODE
#include <linux/version.h>
@@ -15,8 +17,6 @@
#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
#define CONFIG_UDF_FS_MODULE
-#include <linux/udf_fs_i.h>
-#include <linux/udf_fs_sb.h>
#endif
#include "udfend.h"
diff --git a/include/asm-ppc/siginfo.h b/include/asm-ppc/siginfo.h
index 684ad91eb8d7..597b234d1b44 100644
--- a/include/asm-ppc/siginfo.h
+++ b/include/asm-ppc/siginfo.h
@@ -99,7 +99,6 @@ typedef struct siginfo {
/*
* si_code values
- * Digital reserves positive values for kernel-generated signals.
*/
#define SI_USER 0 /* sent by kill, sigsend, raise */
#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */
@@ -109,6 +108,7 @@ typedef struct siginfo {
#define SI_ASYNCIO -4 /* sent by AIO completion */
#define SI_SIGIO -5 /* sent by queued SIGIO */
#define SI_TKILL -6 /* sent by tkill system call */
+#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */
#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
diff --git a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h
index 0ea0afd7e48e..b98527161019 100644
--- a/include/asm-ppc/thread_info.h
+++ b/include/asm-ppc/thread_info.h
@@ -18,10 +18,11 @@
* If you change this, change the TI_* offsets below to match.
*/
struct thread_info {
- struct task_struct *task; /* main task structure */
- struct exec_domain *exec_domain; /* execution domain */
- unsigned long flags; /* low level flags */
- int cpu; /* cpu we're on */
+ struct task_struct *task; /* main task structure */
+ struct exec_domain *exec_domain; /* execution domain */
+ unsigned long flags; /* low level flags */
+ int cpu; /* cpu we're on */
+ int preempt_count; /* not used at present */
};
/*
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d05052fa4461..1600f74d5410 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -648,7 +648,6 @@ struct quota_mount_options
#include <linux/ext3_fs_sb.h>
#include <linux/hpfs_fs_sb.h>
#include <linux/ntfs_fs_sb.h>
-#include <linux/iso_fs_sb.h>
#include <linux/sysv_fs_sb.h>
#include <linux/affs_fs_sb.h>
#include <linux/ufs_fs_sb.h>
@@ -657,7 +656,6 @@ struct quota_mount_options
#include <linux/adfs_fs_sb.h>
#include <linux/reiserfs_fs_sb.h>
#include <linux/bfs_fs_sb.h>
-#include <linux/udf_fs_sb.h>
extern struct list_head super_blocks;
extern spinlock_t sb_lock;
@@ -696,7 +694,6 @@ struct super_block {
struct ext3_sb_info ext3_sb;
struct hpfs_sb_info hpfs_sb;
struct ntfs_sb_info ntfs_sb;
- struct isofs_sb_info isofs_sb;
struct sysv_sb_info sysv_sb;
struct affs_sb_info affs_sb;
struct ufs_sb_info ufs_sb;
@@ -706,7 +703,6 @@ struct super_block {
struct adfs_sb_info adfs_sb;
struct reiserfs_sb_info reiserfs_sb;
struct bfs_sb_info bfs_sb;
- struct udf_sb_info udf_sb;
void *generic_sbp;
} u;
/*
diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h
index cffc0323325d..4f57c1174598 100644
--- a/include/linux/hiddev.h
+++ b/include/linux/hiddev.h
@@ -119,6 +119,7 @@ struct hiddev_usage_ref {
__s32 value;
};
+#define HID_FIELD_INDEX_NONE 0xffffffff
/*
* Protocol version.
@@ -143,6 +144,15 @@ struct hiddev_usage_ref {
#define HIDIOCGUSAGE _IOWR('H', 0x0B, struct hiddev_usage_ref)
#define HIDIOCSUSAGE _IOW('H', 0x0C, struct hiddev_usage_ref)
#define HIDIOCGUCODE _IOWR('H', 0x0D, struct hiddev_usage_ref)
+#define HIDIOCGFLAG _IOR('H', 0x0E, int)
+#define HIDIOCSFLAG _IOW('H', 0x0F, int)
+
+/*
+ * Flags to be used in HIDIOCSFLAG
+ */
+#define HIDDEV_FLAG_UREF 0x1
+#define HIDDEV_FLAG_REPORT 0x2
+#define HIDDEV_FLAGS 0x3
/* To traverse the input report descriptor info for a HID device, perform the
* following:
@@ -179,7 +189,7 @@ struct hiddev_usage_ref {
#ifdef CONFIG_USB_HIDDEV
int hiddev_connect(struct hid_device *);
void hiddev_disconnect(struct hid_device *);
-void hiddev_hid_event(struct hid_device *, unsigned int usage, int value);
+void hiddev_hid_event(struct hid_device *, struct hiddev_usage_ref *ref);
int __init hiddev_init(void);
void __exit hiddev_exit(void);
#else
diff --git a/include/linux/if_wanpipe.h b/include/linux/if_wanpipe.h
index 544d818d9f73..c4cd29a162fe 100644
--- a/include/linux/if_wanpipe.h
+++ b/include/linux/if_wanpipe.h
@@ -122,6 +122,7 @@ struct wanpipe_opt
unsigned poll_cnt;
unsigned char force; /* Used to force sock release */
atomic_t packet_sent;
+ unsigned short num;
};
#define wp_sk(__sk) ((struct wanpipe_opt *)(__sk)->protinfo)
diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h
index b235c3ea9f23..3520e22a2af8 100644
--- a/include/linux/iso_fs.h
+++ b/include/linux/iso_fs.h
@@ -160,7 +160,6 @@ struct iso_directory_record {
#define ISOFS_BUFFER_SIZE(INODE) ((INODE)->i_sb->s_blocksize)
#define ISOFS_BUFFER_BITS(INODE) ((INODE)->i_sb->s_blocksize_bits)
-#define ISOFS_ZONE_BITS(INODE) ((INODE)->i_sb->u.isofs_sb.s_log_zone_size)
#define ISOFS_SUPER_MAGIC 0x9660
@@ -171,6 +170,12 @@ struct iso_directory_record {
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include <linux/iso_fs_i.h>
+#include <linux/iso_fs_sb.h>
+
+static inline struct isofs_sb_info *ISOFS_SB(struct super_block *sb)
+{
+ return sb->u.generic_sbp;
+}
static inline struct iso_inode_info *ISOFS_I(struct inode *inode)
{
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 5fa94340daf9..b93dd0167679 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
static int kill_proto(const struct ip_conntrack *i, void *data)
{
- return (i->tuplehash[IP_CT_DIR_ORIGINAL].dst.protonum ==
+ return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
*((u_int8_t *) data));
}
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 88a4e1356ed3..0a9f62073788 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -19,6 +19,7 @@
* Alan Cox.
* X25 socket Author: Jonathan Naylor.
* ============================================================================
+* Mar 15, 2002 Arnaldo C. Melo o Use wp_sk()->num, as it isnt anymore in sock
* Apr 25, 2000 Nenad Corbic o Added the ability to send zero length packets.
* Mar 13, 2000 Nenad Corbic o Added a tx buffer check via ioctl call.
* Mar 06, 2000 Nenad Corbic o Fixed the corrupt sock lcn problem.
@@ -164,11 +165,11 @@ static void dbg_kfree(void * v, int line) {
/* List of all wanpipe sockets. */
-struct sock * wanpipe_sklist = NULL;
+struct sock* wanpipe_sklist;
static rwlock_t wanpipe_sklist_lock = RW_LOCK_UNLOCKED;
atomic_t wanpipe_socks_nr;
-static unsigned long wanpipe_tx_critical=0;
+static unsigned long wanpipe_tx_critical;
#if 0
/* Private wanpipe socket structures. */
@@ -187,9 +188,9 @@ struct wanpipe_opt
};
#endif
-static int sk_count=0;
+static int sk_count;
extern struct proto_ops wanpipe_ops;
-static unsigned long find_free_critical=0;
+static unsigned long find_free_critical;
static void wanpipe_unlink_driver (struct sock *);
static void wanpipe_link_driver (netdevice_t *,struct sock *sk);
@@ -400,9 +401,9 @@ static int wanpipe_listen_rcv (struct sk_buff *skb, struct sock *sk)
card->u.x.svc_to_dev_map[(chan->lcn%MAX_X25_LCN)] = dev;
newsk->zapped=0;
- newsk->num = htons(X25_PROT);
+ newwp->num = htons(X25_PROT);
- if (wanpipe_do_bind(newsk,dev,newsk->num)){
+ if (wanpipe_do_bind(newsk, dev, newwp->num)) {
wanpipe_kill_sock_irq (newsk);
release_device(dev);
return -EINVAL;
@@ -470,7 +471,7 @@ static struct sock *wanpipe_make_new(struct sock *osk)
sk->socket = osk->socket;
sk->priority = osk->priority;
sk->protocol = osk->protocol;
- sk->num = osk->num;
+ wp_sk(sk)->num = wp_sk(osk)->num;
sk->rcvbuf = osk->rcvbuf;
sk->sndbuf = osk->sndbuf;
sk->debug = osk->debug;
@@ -566,9 +567,11 @@ static int wanpipe_sendmsg(struct socket *sock, struct msghdr *msg, int len,
if (len < sizeof(x25api_hdr_t))
return -EINVAL;
+ wp = wp_sk(sk);
+
if (saddr == NULL) {
ifindex = sk->bound_dev_if;
- proto = sk->num;
+ proto = wp->num;
addr = NULL;
}else{
@@ -648,7 +651,6 @@ static int wanpipe_sendmsg(struct socket *sock, struct msghdr *msg, int len,
}
skb_queue_tail(&sk->write_queue,skb);
- wp = wp_sk(sk);
atomic_inc(&wp->packet_sent);
if (!(test_and_set_bit(0, &wp->timer))){
@@ -998,7 +1000,8 @@ static int wanpipe_release(struct socket *sock, struct socket *peersock)
* Unhook packet receive handler.
*/
- if (sk->num == htons(X25_PROT) && sk->state != WANSOCK_DISCONNECTED && sk->zapped){
+ if (wp->num == htons(X25_PROT) &&
+ sk->state != WANSOCK_DISCONNECTED && sk->zapped) {
netdevice_t *dev = dev_get_by_index(sk->bound_dev_if);
wanpipe_common_t *chan;
if (dev){
@@ -1206,7 +1209,8 @@ static void wanpipe_kill_sock_timer (unsigned long data)
write_unlock(&wanpipe_sklist_lock);
- if (sk->num == htons(X25_PROT) && sk->state != WANSOCK_DISCONNECTED){
+ if (wp_sk(sk)->num == htons(X25_PROT) &&
+ sk->state != WANSOCK_DISCONNECTED){
netdevice_t *dev = dev_get_by_index(sk->bound_dev_if);
wanpipe_common_t *chan;
if (dev){
@@ -1352,6 +1356,7 @@ static void wanpipe_kill_sock_irq (struct sock *sk)
static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol)
{
+ wanpipe_opt *wp = wp_sk(sk);
wanpipe_common_t *chan=NULL;
int err=0;
@@ -1360,7 +1365,7 @@ static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol)
goto bind_unlock_exit;
}
- sk->num = protocol;
+ wp->num = protocol;
if (protocol == 0){
release_device(dev);
@@ -1373,7 +1378,7 @@ static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol)
chan=dev->priv;
sk->state = chan->state;
- if (sk->num == htons(X25_PROT) &&
+ if (wp->num == htons(X25_PROT) &&
sk->state != WANSOCK_DISCONNECTED &&
sk->state != WANSOCK_CONNECTING){
DBG_PRINTK(KERN_INFO
@@ -1388,7 +1393,7 @@ static int wanpipe_do_bind(struct sock *sk, netdevice_t *dev, int protocol)
sk->bound_dev_if = dev->ifindex;
/* X25 Specific option */
- if (sk->num == htons(X25_PROT))
+ if (wp->num == htons(X25_PROT))
wp_sk(sk)->svc = chan->svc;
} else {
@@ -1421,6 +1426,7 @@ static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_le
{
struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)uaddr;
struct sock *sk=sock->sk;
+ wanpipe_opt *wp = wp_sk(sk);
netdevice_t *dev = NULL;
sdla_t *card=NULL;
char name[15];
@@ -1462,7 +1468,7 @@ static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_le
return err;
if (sll->sll_protocol)
- sk->num = sll->sll_protocol;
+ wp->num = sll->sll_protocol;
sk->state = WANSOCK_BIND_LISTEN;
return 0;
@@ -1509,7 +1515,7 @@ static int wanpipe_bind(struct socket *sock, struct sockaddr *uaddr, int addr_le
return -EINVAL;
}
- return wanpipe_do_bind(sk, dev, sll->sll_protocol ? : sk->num);
+ return wanpipe_do_bind(sk, dev, sll->sll_protocol ? : wp->num);
}
/*============================================================
@@ -1613,7 +1619,7 @@ static int wanpipe_create(struct socket *sock, int protocol)
sk->zapped=0;
sk->family = PF_WANPIPE;
- sk->num = protocol;
+ wp_sk(sk)->num = protocol;
sk->state = WANSOCK_DISCONNECTED;
sk->ack_backlog = 0;
sk->bound_dev_if=0;
@@ -1774,7 +1780,7 @@ static int wanpipe_getname(struct socket *sock, struct sockaddr *uaddr,
sll->sll_family = AF_WANPIPE;
sll->sll_ifindex = sk->bound_dev_if;
- sll->sll_protocol = sk->num;
+ sll->sll_protocol = wp_sk(sk)->num;
dev = dev_get_by_index(sk->bound_dev_if);
if (dev) {
sll->sll_hatype = dev->type;
@@ -1836,7 +1842,8 @@ static int wanpipe_notifier(struct notifier_block *this, unsigned long msg, void
}
break;
case NETDEV_UP:
- if (dev->ifindex == sk->bound_dev_if && sk->num && !sk->zapped) {
+ if (dev->ifindex == sk->bound_dev_if &&
+ po->num && !sk->zapped) {
printk(KERN_INFO "wansock: Registering Device: %s\n",
dev->name);
wanpipe_link_driver(dev,sk);
@@ -2242,7 +2249,7 @@ unsigned int wanpipe_poll(struct file * file, struct socket *sock, poll_table *w
* where multiple packets can be pending in the socket
* transmit queue */
- if (sk->num == htons(X25_PROT)){
+ if (wp_sk(sk)->num == htons(X25_PROT)) {
if (atomic_read(&wp_sk(sk)->packet_sent))
return mask;
}
@@ -2274,7 +2281,7 @@ static int wanpipe_listen(struct socket *sock, int backlog)
/* This is x25 specific area if protocol doesn't
* match, return error */
- if (sk->num != htons(X25_PROT))
+ if (wp_sk(sk)->num != htons(X25_PROT))
return -EINVAL;
if (sk->state == WANSOCK_BIND_LISTEN) {
@@ -2352,7 +2359,7 @@ static int wanpipe_exec_cmd(struct sock *sk, int cmd, unsigned int flags)
/* This is x25 specific area if protocol doesn't
* match, return error */
- if (sk->num != htons(X25_PROT))
+ if (wp->num != htons(X25_PROT))
return -EINVAL;
@@ -2535,7 +2542,7 @@ static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags
if (sk->state != WANSOCK_LISTEN)
return -EINVAL;
- if (sk->num != htons(X25_PROT))
+ if (wp_sk(sk)->num != htons(X25_PROT))
return -EINVAL;
add_wait_queue(sk->sleep,&wait);
@@ -2628,7 +2635,7 @@ static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr
netdevice_t *dev;
int err;
- if (sk->num != htons(X25_PROT))
+ if (wp_sk(sk)->num != htons(X25_PROT))
return -EINVAL;
if (sk->state == WANSOCK_CONNECTED)