aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/busy_poll.h
blob: 829627d7b8460e1739da979a3937056dde92a48e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
 * net busy poll support
 * Copyright(c) 2013 Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Author: Eliezer Tamir
 *
 * Contact Information:
 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
 */

#ifndef _LINUX_NET_BUSY_POLL_H
#define _LINUX_NET_BUSY_POLL_H

#include <linux/netdevice.h>
#include <net/ip.h>

#ifdef CONFIG_NET_RX_BUSY_POLL

struct napi_struct;
extern unsigned int sysctl_net_busy_read __read_mostly;
extern unsigned int sysctl_net_busy_poll __read_mostly;

/* return values from ndo_ll_poll */
#define LL_FLUSH_FAILED		-1
#define LL_FLUSH_BUSY		-2

static inline bool net_busy_loop_on(void)
{
	return sysctl_net_busy_poll;
}

/* a wrapper to make debug_smp_processor_id() happy
 * we can use sched_clock() because we don't care much about precision
 * we only care that the average is bounded
 */
#ifdef CONFIG_DEBUG_PREEMPT
static inline u64 busy_loop_us_clock(void)
{
	u64 rc;

	preempt_disable_notrace();
	rc = sched_clock();
	preempt_enable_no_resched_notrace();

	return rc >> 10;
}
#else /* CONFIG_DEBUG_PREEMPT */
static inline u64 busy_loop_us_clock(void)
{
	return sched_clock() >> 10;
}
#endif /* CONFIG_DEBUG_PREEMPT */

static inline unsigned long sk_busy_loop_end_time(struct sock *sk)
{
	return busy_loop_us_clock() + ACCESS_ONCE(sk->sk_ll_usec);
}

/* in poll/select we use the global sysctl_net_ll_poll value */
static inline unsigned long busy_loop_end_time(void)
{
	return busy_loop_us_clock() + ACCESS_ONCE(sysctl_net_busy_poll);
}

static inline bool sk_can_busy_loop(struct sock *sk)
{
	return sk->sk_ll_usec && sk->sk_napi_id &&
	       !need_resched() && !signal_pending(current);
}


static inline bool busy_loop_timeout(unsigned long end_time)
{
	unsigned long now = busy_loop_us_clock();

	return time_after(now, end_time);
}

/* when used in sock_poll() nonblock is known at compile time to be true
 * so the loop and end_time will be optimized out
 */
static inline bool sk_busy_loop(struct sock *sk, int nonblock)
{
	unsigned long end_time = !nonblock ? sk_busy_loop_end_time(sk) : 0;
	const struct net_device_ops *ops;
	struct napi_struct *napi;
	int rc = false;

	/*
	 * rcu read lock for napi hash
	 * bh so we don't race with net_rx_action
	 */
	rcu_read_lock_bh();

	napi = napi_by_id(sk->sk_napi_id);
	if (!napi)
		goto out;

	ops = napi->dev->netdev_ops;
	if (!ops->ndo_busy_poll)
		goto out;

	do {
		rc = ops->ndo_busy_poll(napi);

		if (rc == LL_FLUSH_FAILED)
			break; /* permanent failure */

		if (rc > 0)
			/* local bh are disabled so it is ok to use _BH */
			NET_ADD_STATS_BH(sock_net(sk),
					 LINUX_MIB_BUSYPOLLRXPACKETS, rc);
		cpu_relax();

	} while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) &&
		 !need_resched() && !busy_loop_timeout(end_time));

	rc = !skb_queue_empty(&sk->sk_receive_queue);
out:
	rcu_read_unlock_bh();
	return rc;
}

/* used in the NIC receive handler to mark the skb */
static inline void skb_mark_napi_id(struct sk_buff *skb,
				    struct napi_struct *napi)
{
	skb->napi_id = napi->napi_id;
}

/* used in the protocol hanlder to propagate the napi_id to the socket */
static inline void sk_mark_napi_id(struct sock *sk, struct sk_buff *skb)
{
	sk->sk_napi_id = skb->napi_id;
}

#else /* CONFIG_NET_RX_BUSY_POLL */
static inline unsigned long net_busy_loop_on(void)
{
	return 0;
}

static inline unsigned long busy_loop_end_time(void)
{
	return 0;
}

static inline bool sk_can_busy_loop(struct sock *sk)
{
	return false;
}

static inline void skb_mark_napi_id(struct sk_buff *skb,
				    struct napi_struct *napi)
{
}

static inline void sk_mark_napi_id(struct sock *sk, struct sk_buff *skb)
{
}

static inline bool busy_loop_timeout(unsigned long end_time)
{
	return true;
}

static inline bool sk_busy_loop(struct sock *sk, int nonblock)
{
	return false;
}

#endif /* CONFIG_NET_RX_BUSY_POLL */
#endif /* _LINUX_NET_BUSY_POLL_H */
lass="hl kwa">case XFER_UDMA_7: return("UDMA 7"); case XFER_UDMA_6: return("UDMA 6"); case XFER_UDMA_5: return("UDMA 5"); case XFER_UDMA_4: return("UDMA 4"); case XFER_UDMA_3: return("UDMA 3"); case XFER_UDMA_2: return("UDMA 2"); case XFER_UDMA_1: return("UDMA 1"); case XFER_UDMA_0: return("UDMA 0"); case XFER_MW_DMA_2: return("MW DMA 2"); case XFER_MW_DMA_1: return("MW DMA 1"); case XFER_MW_DMA_0: return("MW DMA 0"); case XFER_SW_DMA_2: return("SW DMA 2"); case XFER_SW_DMA_1: return("SW DMA 1"); case XFER_SW_DMA_0: return("SW DMA 0"); case XFER_PIO_4: return("PIO 4"); case XFER_PIO_3: return("PIO 3"); case XFER_PIO_2: return("PIO 2"); case XFER_PIO_1: return("PIO 1"); case XFER_PIO_0: return("PIO 0"); case XFER_PIO_SLOW: return("PIO SLOW"); default: return("XFER ERROR"); } } EXPORT_SYMBOL(ide_xfer_verbose); /** * ide_rate_filter - filter transfer mode * @drive: IDE device * @speed: desired speed * * Given the available transfer modes this function returns * the best available speed at or below the speed requested. * * TODO: check device PIO capabilities */ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = drive->hwif; u8 mode = ide_find_dma_mode(drive, speed); if (mode == 0) { if (hwif->pio_mask) mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0; else mode = XFER_PIO_4; } // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); return min(speed, mode); } int ide_use_fast_pio(ide_drive_t *drive) { struct hd_driveid *id = drive->id; if ((id->capability & 1) && drive->autodma) return 1; if ((id->capability & 8) || (id->field_valid & 2)) return 1; return 0; } EXPORT_SYMBOL_GPL(ide_use_fast_pio); /* * Standard (generic) timings for PIO modes, from ATA2 specification. * These timings are for access to the IDE data port register *only*. * Some drives may specify a mode, while also specifying a different * value for cycle_time (from drive identification data). */ const ide_pio_timings_t ide_pio_timings[6] = { { 70, 165, 600 }, /* PIO Mode 0 */ { 50, 125, 383 }, /* PIO Mode 1 */ { 30, 100, 240 }, /* PIO Mode 2 */ { 30, 80, 180 }, /* PIO Mode 3 with IORDY */ { 25, 70, 120 }, /* PIO Mode 4 with IORDY */ { 20, 50, 100 } /* PIO Mode 5 with IORDY (nonstandard) */ }; EXPORT_SYMBOL_GPL(ide_pio_timings); /* * Shared data/functions for determining best PIO mode for an IDE drive. * Most of this stuff originally lived in cmd640.c, and changes to the * ide_pio_blacklist[] table should be made with EXTREME CAUTION to avoid * breaking the fragile cmd640.c support. */ /* * Black list. Some drives incorrectly report their maximal PIO mode, * at least in respect to CMD640. Here we keep info on some known drives. */ static struct ide_pio_info { const char *name; int pio; } ide_pio_blacklist [] = { /* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */ { "Conner Peripherals 540MB - CFS540A", 3 }, { "WDC AC2700", 3 }, { "WDC AC2540", 3 }, { "WDC AC2420", 3 }, { "WDC AC2340", 3 }, { "WDC AC2250", 0 }, { "WDC AC2200", 0 }, { "WDC AC21200", 4 }, { "WDC AC2120", 0 }, { "WDC AC2850", 3 }, { "WDC AC1270", 3 }, { "WDC AC1170", 1 }, { "WDC AC1210", 1 }, { "WDC AC280", 0 }, /* { "WDC AC21000", 4 }, */ { "WDC AC31000", 3 }, { "WDC AC31200", 3 }, /* { "WDC AC31600", 4 }, */ { "Maxtor 7131 AT", 1 }, { "Maxtor 7171 AT", 1 }, { "Maxtor 7213 AT", 1 }, { "Maxtor 7245 AT", 1 }, { "Maxtor 7345 AT", 1 }, { "Maxtor 7546 AT", 3 }, { "Maxtor 7540 AV", 3 }, { "SAMSUNG SHD-3121A", 1 }, { "SAMSUNG SHD-3122A", 1 }, { "SAMSUNG SHD-3172A", 1 }, /* { "ST51080A", 4 }, * { "ST51270A", 4 }, * { "ST31220A", 4 }, * { "ST31640A", 4 }, * { "ST32140A", 4 }, * { "ST3780A", 4 }, */ { "ST5660A", 3 }, { "ST3660A", 3 }, { "ST3630A", 3 }, { "ST3655A", 3 }, { "ST3391A", 3 }, { "ST3390A", 1 }, { "ST3600A", 1 }, { "ST3290A", 0 }, { "ST3144A", 0 }, { "ST3491A", 1 }, /* reports 3, should be 1 or 2 (depending on */ /* drive) according to Seagates FIND-ATA program */ { "QUANTUM ELS127A", 0 }, { "QUANTUM ELS170A", 0 }, { "QUANTUM LPS240A", 0 }, { "QUANTUM LPS210A", 3 }, { "QUANTUM LPS270A", 3 }, { "QUANTUM LPS365A", 3 }, { "QUANTUM LPS540A", 3 }, { "QUANTUM LIGHTNING 540A", 3 }, { "QUANTUM LIGHTNING 730A", 3 }, { "QUANTUM FIREBALL_540", 3 }, /* Older Quantum Fireballs don't work */ { "QUANTUM FIREBALL_640", 3 }, { "QUANTUM FIREBALL_1080", 3 }, { "QUANTUM FIREBALL_1280", 3 }, { NULL, 0 } }; /** * ide_scan_pio_blacklist - check for a blacklisted drive * @model: Drive model string * * This routine searches the ide_pio_blacklist for an entry * matching the start/whole of the supplied model name. * * Returns -1 if no match found. * Otherwise returns the recommended PIO mode from ide_pio_blacklist[]. */ static int ide_scan_pio_blacklist (char *model) { struct ide_pio_info *p; for (p = ide_pio_blacklist; p->name != NULL; p++) { if (strncmp(p->name, model, strlen(p->name)) == 0) return p->pio; } return -1; } unsigned int ide_pio_cycle_time(ide_drive_t *drive, u8 pio) { struct hd_driveid *id = drive->id; int cycle_time = 0; if (id->field_valid & 2) { if (id->capability & 8) cycle_time = id->eide_pio_iordy; else cycle_time = id->eide_pio; } /* conservative "downgrade" for all pre-ATA2 drives */ if (pio < 3) { if (cycle_time && cycle_time < ide_pio_timings[pio].cycle_time) cycle_time = 0; /* use standard timing */ } return cycle_time ? cycle_time : ide_pio_timings[pio].cycle_time; } EXPORT_SYMBOL_GPL(ide_pio_cycle_time); /** * ide_get_best_pio_mode - get PIO mode from drive * @drive: drive to consider * @mode_wanted: preferred mode * @max_mode: highest allowed mode * * This routine returns the recommended PIO settings for a given drive, * based on the drive->id information and the ide_pio_blacklist[]. * * Drive PIO mode is auto-selected if 255 is passed as mode_wanted. * This is used by most chipset support modules when "auto-tuning". */ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode) { int pio_mode; struct hd_driveid* id = drive->id; int overridden = 0; if (mode_wanted != 255) return min_t(u8, mode_wanted, max_mode); if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0 && (pio_mode = ide_scan_pio_blacklist(id->model)) != -1) { printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); } else { pio_mode = id->tPIO; if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ pio_mode = 2; overridden = 1; } if (id->field_valid & 2) { /* drive implements ATA2? */ if (id->capability & 8) { /* IORDY supported? */ if (id->eide_pio_modes & 7) { overridden = 0; if (id->eide_pio_modes & 4) pio_mode = 5; else if (id->eide_pio_modes & 2) pio_mode = 4; else pio_mode = 3; } } } if (overridden) printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n", drive->name); /* * Conservative "downgrade" for all pre-ATA2 drives */ if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_DOWNGRADE) == 0 && pio_mode && pio_mode < 4) { pio_mode--; printk(KERN_INFO "%s: applying conservative " "PIO \"downgrade\"\n", drive->name); } } if (pio_mode > max_mode) pio_mode = max_mode; return pio_mode; } EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); /* req_pio == "255" for auto-tune */ void ide_set_pio(ide_drive_t *drive, u8 req_pio) { ide_hwif_t *hwif = drive->hwif; u8 host_pio, pio; if (hwif->set_pio_mode == NULL) return; BUG_ON(hwif->pio_mask == 0x00); host_pio = fls(hwif->pio_mask) - 1; pio = ide_get_best_pio_mode(drive, req_pio, host_pio); /* * TODO: * - report device max PIO mode * - check req_pio != 255 against device max PIO mode */ printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n", drive->name, host_pio, req_pio, req_pio == 255 ? "(auto-tune)" : "", pio); hwif->set_pio_mode(drive, pio); } EXPORT_SYMBOL_GPL(ide_set_pio); /** * ide_toggle_bounce - handle bounce buffering * @drive: drive to update * @on: on/off boolean * * Enable or disable bounce buffering for the device. Drives move * between PIO and DMA and that changes the rules we need. */ void ide_toggle_bounce(ide_drive_t *drive, int on) { u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ if (!PCI_DMA_BUS_IS_PHYS) { addr = BLK_BOUNCE_ANY; } else if (on && drive->media == ide_disk) { if (HWIF(drive)->pci_dev) addr = HWIF(drive)->pci_dev->dma_mask; } if (drive->queue) blk_queue_bounce_limit(drive->queue, addr); } /** * ide_set_xfer_rate - set transfer rate * @drive: drive to set * @speed: speed to attempt to set * * General helper for setting the speed of an IDE device. This * function knows about user enforced limits from the configuration * which speedproc() does not. High level drivers should never * invoke speedproc() directly. */ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) { ide_hwif_t *hwif = drive->hwif; if (hwif->speedproc == NULL) return -1; rate = ide_rate_filter(drive, rate); if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) { if (hwif->set_pio_mode) hwif->set_pio_mode(drive, rate - XFER_PIO_0); /* * FIXME: this is incorrect to return zero here but * since all users of ide_set_xfer_rate() ignore * the return value it is not a problem currently */ return 0; } return hwif->speedproc(drive, rate); } static void ide_dump_opcode(ide_drive_t *drive) { struct request *rq; u8 opcode = 0; int found = 0; spin_lock(&ide_lock); rq = NULL; if (HWGROUP(drive)) rq = HWGROUP(drive)->rq; spin_unlock(&ide_lock); if (!rq) return; if (rq->cmd_type == REQ_TYPE_ATA_CMD || rq->cmd_type == REQ_TYPE_ATA_TASK) { char *args = rq->buffer; if (args) { opcode = args[0]; found = 1; } } else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { ide_task_t *args = rq->special; if (args) { task_struct_t *tf = (task_struct_t *) args->tfRegister; opcode = tf->command; found = 1; } } printk("ide: failed opcode was: "); if (!found) printk("unknown\n"); else printk("0x%02x\n", opcode); } static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) { ide_hwif_t *hwif = HWIF(drive); unsigned long flags; u8 err = 0; local_irq_save(flags); printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); if (stat & BUSY_STAT) printk("Busy "); else { if (stat & READY_STAT) printk("DriveReady "); if (stat & WRERR_STAT) printk("DeviceFault "); if (stat & SEEK_STAT) printk("SeekComplete "); if (stat & DRQ_STAT) printk("DataRequest "); if (stat & ECC_STAT) printk("CorrectedError "); if (stat & INDEX_STAT) printk("Index "); if (stat & ERR_STAT) printk("Error "); } printk("}\n"); if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { err = hwif->INB(IDE_ERROR_REG); printk("%s: %s: error=0x%02x { ", drive->name, msg, err); if (err & ABRT_ERR) printk("DriveStatusError "); if (err & ICRC_ERR) printk((err & ABRT_ERR) ? "BadCRC " : "BadSector "); if (err & ECC_ERR) printk("UncorrectableError "); if (err & ID_ERR) printk("SectorIdNotFound "); if (err & TRK0_ERR) printk("TrackZeroNotFound "); if (err & MARK_ERR) printk("AddrMarkNotFound "); printk("}"); if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) { if (drive->addressing == 1) { __u64 sectors = 0; u32 low = 0, high = 0; low = ide_read_24(drive); hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); high = ide_read_24(drive); sectors = ((__u64)high << 24) | low; printk(", LBAsect=%llu, high=%d, low=%d", (unsigned long long) sectors, high, low); } else { u8 cur = hwif->INB(IDE_SELECT_REG); if (cur & 0x40) { /* using LBA? */ printk(", LBAsect=%ld", (unsigned long) ((cur&0xf)<<24) |(hwif->INB(IDE_HCYL_REG)<<16) |(hwif->INB(IDE_LCYL_REG)<<8) | hwif->INB(IDE_SECTOR_REG)); } else { printk(", CHS=%d/%d/%d", (hwif->INB(IDE_HCYL_REG)<<8) + hwif->INB(IDE_LCYL_REG), cur & 0xf, hwif->INB(IDE_SECTOR_REG)); } } if (HWGROUP(drive) && HWGROUP(drive)->rq) printk(", sector=%llu", (unsigned long long)HWGROUP(drive)->rq->sector); } printk("\n"); } ide_dump_opcode(drive); local_irq_restore(flags); return err; } /** * ide_dump_atapi_status - print human readable atapi status * @drive: drive that status applies to * @msg: text message to print * @stat: status byte to decode * * Error reporting, in human readable form (luxurious, but a memory hog). */ static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat) { unsigned long flags; atapi_status_t status; atapi_error_t error; status.all = stat; error.all = 0; local_irq_save(flags); printk("%s: %s: status=0x%02x { ", drive->name, msg, stat); if (status.b.bsy) printk("Busy "); else { if (status.b.drdy) printk("DriveReady "); if (status.b.df) printk("DeviceFault "); if (status.b.dsc) printk("SeekComplete "); if (status.b.drq) printk("DataRequest "); if (status.b.corr) printk("CorrectedError "); if (status.b.idx) printk("Index "); if (status.b.check) printk("Error "); } printk("}\n"); if (status.b.check && !status.b.bsy) { error.all = HWIF(drive)->INB(IDE_ERROR_REG); printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all); if (error.b.ili) printk("IllegalLengthIndication "); if (error.b.eom) printk("EndOfMedia "); if (error.b.abrt) printk("AbortedCommand "); if (error.b.mcr) printk("MediaChangeRequested "); if (error.b.sense_key) printk("LastFailedSense=0x%02x ", error.b.sense_key); printk("}\n"); } ide_dump_opcode(drive); local_irq_restore(flags); return error.all; } /** * ide_dump_status - translate ATA/ATAPI error * @drive: drive the error occured on * @msg: information string * @stat: status byte * * Error reporting, in human readable form (luxurious, but a memory hog). * Combines the drive name, message and status byte to provide a * user understandable explanation of the device error. */ u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat) { if (drive->media == ide_disk) return ide_dump_ata_status(drive, msg, stat); return ide_dump_atapi_status(drive, msg, stat); } EXPORT_SYMBOL(ide_dump_status);