summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-24 15:01:17 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-24 15:01:17 -0800
commitf8e6859ea9d06ae1565b21278c4e10fbce5f1eab (patch)
tree263f1ec8127fa4f38e080eebdfe4cfa26d6679e2 /drivers
parenta682e0035494c449e53a57d039f86f75b9e2fe67 (diff)
parentac65e2828d03ddf84e9fe1fb6d110d8de933dc22 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Pull sparc updates from David Miller: 1) Support multiple huge page sizes, from Nitin Gupta. 2) Improve boot time on large memory configurations, from Pavel Tatashin. 3) Make BRK handling more consistent and documented, from Vijay Kumar. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: sparc64: Fix build error in flush_tsb_user_page sparc64: memblock resizes are not handled properly sparc64: use latency groups to improve add_node_ranges speed sparc64: Add 64K page size support sparc64: Multi-page size support Documentation/sparc: Steps for sending break on sunhv console sparc64: Send break twice from console to return to boot prom sparc64: Migrate hvcons irq to panicked cpu sparc64: Set cpu state to offline when stopped sunvdc: Add support for setting physical sector size sparc64: fix for user probes in high memory sparc: topology_64.h: Fix condition for including cpudata.h sparc32: mm: srmmu: add __ro_after_init to sparc32_cachetlb_ops structures
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/sunvdc.c18
-rw-r--r--drivers/tty/serial/sunhv.c12
2 files changed, 28 insertions, 2 deletions
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index cab157331c4e..3f3a3ab3d50a 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -34,6 +34,7 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
#define VDC_TX_RING_SIZE 512
+#define VDC_DEFAULT_BLK_SIZE 512
#define WAITING_FOR_LINK_UP 0x01
#define WAITING_FOR_TX_SPACE 0x02
@@ -73,6 +74,7 @@ struct vdc_port {
u32 vdisk_size;
u8 vdisk_type;
u8 vdisk_mtype;
+ u32 vdisk_phys_blksz;
char disk_name[32];
};
@@ -88,6 +90,7 @@ static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
/* Ordered from largest major to lowest */
static struct vio_version vdc_versions[] = {
+ { .major = 1, .minor = 2 },
{ .major = 1, .minor = 1 },
{ .major = 1, .minor = 0 },
};
@@ -271,6 +274,11 @@ static int vdc_handle_attr(struct vio_driver_state *vio, void *arg)
if (pkt->max_xfer_size < port->max_xfer_size)
port->max_xfer_size = pkt->max_xfer_size;
port->vdisk_block_size = pkt->vdisk_block_size;
+
+ port->vdisk_phys_blksz = VDC_DEFAULT_BLK_SIZE;
+ if (vdc_version_supported(port, 1, 2))
+ port->vdisk_phys_blksz = pkt->phys_block_size;
+
return 0;
} else {
printk(KERN_ERR PFX "%s: Attribute NACK\n", vio->name);
@@ -754,6 +762,12 @@ static int probe_disk(struct vdc_port *port)
if (err)
return err;
+ /* Using version 1.2 means vdisk_phys_blksz should be set unless the
+ * disk is reserved by another system.
+ */
+ if (vdc_version_supported(port, 1, 2) && !port->vdisk_phys_blksz)
+ return -ENODEV;
+
if (vdc_version_supported(port, 1, 1)) {
/* vdisk_size should be set during the handshake, if it wasn't
* then the underlying disk is reserved by another system
@@ -829,6 +843,8 @@ static int probe_disk(struct vdc_port *port)
}
}
+ blk_queue_physical_block_size(q, port->vdisk_phys_blksz);
+
pr_info(PFX "%s: %u sectors (%u MB) protocol %d.%d\n",
g->disk_name,
port->vdisk_size, (port->vdisk_size >> (20 - 9)),
@@ -910,7 +926,7 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
if (err)
goto err_out_free_port;
- port->vdisk_block_size = 512;
+ port->vdisk_block_size = VDC_DEFAULT_BLK_SIZE;
port->max_xfer_size = ((128 * 1024) / port->vdisk_block_size);
port->ring_cookies = ((port->max_xfer_size *
port->vdisk_block_size) / PAGE_SIZE) + 2;
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index 73abd89c0108..46e46894e918 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -116,7 +116,7 @@ static int receive_chars_getchar(struct uart_port *port)
static int receive_chars_read(struct uart_port *port)
{
- int saw_console_brk = 0;
+ static int saw_console_brk;
int limit = 10000;
while (limit-- > 0) {
@@ -128,6 +128,9 @@ static int receive_chars_read(struct uart_port *port)
bytes_read = 0;
if (stat == CON_BREAK) {
+ if (saw_console_brk)
+ sun_do_break();
+
if (uart_handle_break(port))
continue;
saw_console_brk = 1;
@@ -151,6 +154,7 @@ static int receive_chars_read(struct uart_port *port)
if (port->sysrq != 0 && *con_read_page) {
for (i = 0; i < bytes_read; i++)
uart_handle_sysrq_char(port, con_read_page[i]);
+ saw_console_brk = 0;
}
if (port->state == NULL)
@@ -398,6 +402,12 @@ static struct uart_driver sunhv_reg = {
static struct uart_port *sunhv_port;
+void sunhv_migrate_hvcons_irq(int cpu)
+{
+ /* Migrate hvcons irq to param cpu */
+ irq_force_affinity(sunhv_port->irq, cpumask_of(cpu));
+}
+
/* Copy 's' into the con_write_page, decoding "\n" into
* "\r\n" along the way. We have to return two lengths
* because the caller needs to know how much to advance